cyfaust 0.1.0__cp311-cp311-macosx_15_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (693) hide show
  1. cyfaust/CMakeLists.txt +93 -0
  2. cyfaust/__init__.py +0 -0
  3. cyfaust/__main__.py +819 -0
  4. cyfaust/box.pxd +46 -0
  5. cyfaust/box.pyx +2459 -0
  6. cyfaust/common.pxd +5 -0
  7. cyfaust/common.pyx +61 -0
  8. cyfaust/cyfaust.cpython-311-darwin.so +0 -0
  9. cyfaust/faust_box.pxd +298 -0
  10. cyfaust/faust_box_oo.pyx +66 -0
  11. cyfaust/faust_gui.pxd +261 -0
  12. cyfaust/faust_interp.pxd +160 -0
  13. cyfaust/faust_player.pxd +80 -0
  14. cyfaust/faust_signal.pxd +257 -0
  15. cyfaust/gui_statics.cpp +15 -0
  16. cyfaust/interp.pyx +673 -0
  17. cyfaust/player.cpp +32519 -0
  18. cyfaust/player.pyx +191 -0
  19. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUBase.cpp +2327 -0
  20. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUBase.h +1019 -0
  21. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUDispatch.cpp +423 -0
  22. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUDispatch.h +82 -0
  23. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUInputElement.cpp +151 -0
  24. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUInputElement.h +119 -0
  25. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUOutputElement.cpp +62 -0
  26. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUOutputElement.h +66 -0
  27. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUPlugInDispatch.cpp +615 -0
  28. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUPlugInDispatch.h +128 -0
  29. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUScopeElement.cpp +512 -0
  30. cyfaust/resources/architecture/AU/AUPublic/AUBase/AUScopeElement.h +544 -0
  31. cyfaust/resources/architecture/AU/AUPublic/AUBase/ComponentBase.cpp +370 -0
  32. cyfaust/resources/architecture/AU/AUPublic/AUBase/ComponentBase.h +340 -0
  33. cyfaust/resources/architecture/AU/AUPublic/AUEffectBase/AUEffectBase.cpp +463 -0
  34. cyfaust/resources/architecture/AU/AUPublic/AUEffectBase/AUEffectBase.h +391 -0
  35. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/AUInstrumentBase.cpp +837 -0
  36. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/AUInstrumentBase.h +267 -0
  37. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/AUMIDIBase.cpp +495 -0
  38. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/AUMIDIBase.h +213 -0
  39. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/LockFreeFIFO.h +168 -0
  40. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/MIDIControlHandler.h +92 -0
  41. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/MusicDeviceBase.cpp +354 -0
  42. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/MusicDeviceBase.h +126 -0
  43. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthElement.cpp +419 -0
  44. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthElement.h +227 -0
  45. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthEvent.h +145 -0
  46. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthNote.cpp +138 -0
  47. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthNote.h +186 -0
  48. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthNoteList.cpp +93 -0
  49. cyfaust/resources/architecture/AU/AUPublic/AUInstrumentBase/SynthNoteList.h +232 -0
  50. cyfaust/resources/architecture/AU/AUPublic/Utility/AUBaseHelper.cpp +134 -0
  51. cyfaust/resources/architecture/AU/AUPublic/Utility/AUBaseHelper.h +80 -0
  52. cyfaust/resources/architecture/AU/AUPublic/Utility/AUBuffer.cpp +217 -0
  53. cyfaust/resources/architecture/AU/AUPublic/Utility/AUBuffer.h +267 -0
  54. cyfaust/resources/architecture/AU/AUPublic/Utility/AUMIDIDefs.h +136 -0
  55. cyfaust/resources/architecture/AU/AUPublic/Utility/AUSilentTimeout.h +93 -0
  56. cyfaust/resources/architecture/AU/English.lproj/InfoPlist.strings +0 -0
  57. cyfaust/resources/architecture/AU/FaustAU.exp +2 -0
  58. cyfaust/resources/architecture/AU/FaustAU.xcodeproj/project.pbxproj +968 -0
  59. cyfaust/resources/architecture/AU/FaustAU.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  60. cyfaust/resources/architecture/AU/FaustAUCustomView.plist +14 -0
  61. cyfaust/resources/architecture/AU/Info.plist +47 -0
  62. cyfaust/resources/architecture/AU/PublicUtility/CAAtomic.h +305 -0
  63. cyfaust/resources/architecture/AU/PublicUtility/CAAtomicStack.h +239 -0
  64. cyfaust/resources/architecture/AU/PublicUtility/CAAudioChannelLayout.cpp +153 -0
  65. cyfaust/resources/architecture/AU/PublicUtility/CAAudioChannelLayout.h +199 -0
  66. cyfaust/resources/architecture/AU/PublicUtility/CAAutoDisposer.h +508 -0
  67. cyfaust/resources/architecture/AU/PublicUtility/CABufferList.cpp +264 -0
  68. cyfaust/resources/architecture/AU/PublicUtility/CABufferList.h +319 -0
  69. cyfaust/resources/architecture/AU/PublicUtility/CAByteOrder.h +161 -0
  70. cyfaust/resources/architecture/AU/PublicUtility/CADebugMacros.cpp +88 -0
  71. cyfaust/resources/architecture/AU/PublicUtility/CADebugMacros.h +580 -0
  72. cyfaust/resources/architecture/AU/PublicUtility/CADebugPrintf.cpp +89 -0
  73. cyfaust/resources/architecture/AU/PublicUtility/CADebugPrintf.h +115 -0
  74. cyfaust/resources/architecture/AU/PublicUtility/CADebugger.cpp +77 -0
  75. cyfaust/resources/architecture/AU/PublicUtility/CADebugger.h +56 -0
  76. cyfaust/resources/architecture/AU/PublicUtility/CAException.h +83 -0
  77. cyfaust/resources/architecture/AU/PublicUtility/CAGuard.cpp +339 -0
  78. cyfaust/resources/architecture/AU/PublicUtility/CAGuard.h +133 -0
  79. cyfaust/resources/architecture/AU/PublicUtility/CAHostTimeBase.cpp +110 -0
  80. cyfaust/resources/architecture/AU/PublicUtility/CAHostTimeBase.h +231 -0
  81. cyfaust/resources/architecture/AU/PublicUtility/CALogMacros.h +140 -0
  82. cyfaust/resources/architecture/AU/PublicUtility/CAMath.h +68 -0
  83. cyfaust/resources/architecture/AU/PublicUtility/CAMutex.cpp +345 -0
  84. cyfaust/resources/architecture/AU/PublicUtility/CAMutex.h +163 -0
  85. cyfaust/resources/architecture/AU/PublicUtility/CAReferenceCounted.h +87 -0
  86. cyfaust/resources/architecture/AU/PublicUtility/CAStreamBasicDescription.cpp +795 -0
  87. cyfaust/resources/architecture/AU/PublicUtility/CAStreamBasicDescription.h +409 -0
  88. cyfaust/resources/architecture/AU/PublicUtility/CAThreadSafeList.h +255 -0
  89. cyfaust/resources/architecture/AU/PublicUtility/CAVectorUnit.cpp +191 -0
  90. cyfaust/resources/architecture/AU/PublicUtility/CAVectorUnit.h +100 -0
  91. cyfaust/resources/architecture/AU/PublicUtility/CAVectorUnitTypes.h +59 -0
  92. cyfaust/resources/architecture/AU/PublicUtility/CAXException.cpp +49 -0
  93. cyfaust/resources/architecture/AU/PublicUtility/CAXException.h +338 -0
  94. cyfaust/resources/architecture/AU/SectionPatternLight.tiff +0 -0
  95. cyfaust/resources/architecture/AU/Source/AUSource/FaustAU.h +38 -0
  96. cyfaust/resources/architecture/AU/Source/AUSource/FaustAU.r +153 -0
  97. cyfaust/resources/architecture/AU/Source/AUSource/FaustAUVersion.h +64 -0
  98. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Bargraph.h +18 -0
  99. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Bargraph.m +21 -0
  100. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Button.h +20 -0
  101. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Button.m +56 -0
  102. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_CustomView.h +87 -0
  103. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_CustomView.m +834 -0
  104. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_CustomViewFactory.h +13 -0
  105. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_CustomViewFactory.m +22 -0
  106. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Knob.h +81 -0
  107. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Knob.m +199 -0
  108. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Slider.h +18 -0
  109. cyfaust/resources/architecture/AU/Source/CocoaUI/FaustAU_Slider.m +21 -0
  110. cyfaust/resources/architecture/AU/version.plist +16 -0
  111. cyfaust/resources/architecture/VST/Info.plist +28 -0
  112. cyfaust/resources/architecture/VST/PkgInfo +1 -0
  113. cyfaust/resources/architecture/VST/README +11 -0
  114. cyfaust/resources/architecture/VST/VST.xcode/project.pbxproj +655 -0
  115. cyfaust/resources/architecture/alsa-console.cpp +246 -0
  116. cyfaust/resources/architecture/alsa-gtk.cpp +220 -0
  117. cyfaust/resources/architecture/alsa-qt.cpp +229 -0
  118. cyfaust/resources/architecture/api/DspFaust.cpp +612 -0
  119. cyfaust/resources/architecture/api/DspFaust.h +511 -0
  120. cyfaust/resources/architecture/api/README.md +237 -0
  121. cyfaust/resources/architecture/api/doc/Generic.md +38 -0
  122. cyfaust/resources/architecture/au-effect.cpp +487 -0
  123. cyfaust/resources/architecture/au-instrument.cpp +573 -0
  124. cyfaust/resources/architecture/bench.cpp +91 -0
  125. cyfaust/resources/architecture/c-jack-gtk.c +227 -0
  126. cyfaust/resources/architecture/ca-gtk.cpp +284 -0
  127. cyfaust/resources/architecture/ca-qt.cpp +424 -0
  128. cyfaust/resources/architecture/cpal.rs +195 -0
  129. cyfaust/resources/architecture/csound.cpp +245 -0
  130. cyfaust/resources/architecture/csvplot.cpp +227 -0
  131. cyfaust/resources/architecture/daisy/Makefile +14 -0
  132. cyfaust/resources/architecture/daisy/README.md +50 -0
  133. cyfaust/resources/architecture/daisy/ex_faust.cpp +173 -0
  134. cyfaust/resources/architecture/dssi.cpp +1262 -0
  135. cyfaust/resources/architecture/dummy-mem.cpp +186 -0
  136. cyfaust/resources/architecture/dummy.cpp +294 -0
  137. cyfaust/resources/architecture/faust/au/AUUI.h +404 -0
  138. cyfaust/resources/architecture/faust/audio/alsa-dsp.h +693 -0
  139. cyfaust/resources/architecture/faust/audio/android-dsp.h +583 -0
  140. cyfaust/resources/architecture/faust/audio/audio.h +115 -0
  141. cyfaust/resources/architecture/faust/audio/channels.h +122 -0
  142. cyfaust/resources/architecture/faust/audio/coreaudio-dsp.h +1543 -0
  143. cyfaust/resources/architecture/faust/audio/coreaudio-ios-dsp.h +743 -0
  144. cyfaust/resources/architecture/faust/audio/dummy-audio.h +255 -0
  145. cyfaust/resources/architecture/faust/audio/esp32-dsp.h +284 -0
  146. cyfaust/resources/architecture/faust/audio/fpe.h +164 -0
  147. cyfaust/resources/architecture/faust/audio/jack-dsp.h +534 -0
  148. cyfaust/resources/architecture/faust/audio/juce-dsp.h +119 -0
  149. cyfaust/resources/architecture/faust/audio/netjack-dsp.h +354 -0
  150. cyfaust/resources/architecture/faust/audio/oboe-dsp.h +308 -0
  151. cyfaust/resources/architecture/faust/audio/ofaudio-dsp.h +155 -0
  152. cyfaust/resources/architecture/faust/audio/opensles-android-dsp.h +631 -0
  153. cyfaust/resources/architecture/faust/audio/osc-dsp.h +120 -0
  154. cyfaust/resources/architecture/faust/audio/portaudio-dsp.h +236 -0
  155. cyfaust/resources/architecture/faust/audio/rtaudio-dsp.h +241 -0
  156. cyfaust/resources/architecture/faust/audio/samAudio.h +140 -0
  157. cyfaust/resources/architecture/faust/audio/teensy-dsp.h +171 -0
  158. cyfaust/resources/architecture/faust/dsp/cmajor-cpp-dsp.h +253 -0
  159. cyfaust/resources/architecture/faust/dsp/cmajorpatch-dsp.h +483 -0
  160. cyfaust/resources/architecture/faust/dsp/cpp-dsp-adapter.h +38 -0
  161. cyfaust/resources/architecture/faust/dsp/dsp-adapter.h +836 -0
  162. cyfaust/resources/architecture/faust/dsp/dsp-bench.h +611 -0
  163. cyfaust/resources/architecture/faust/dsp/dsp-checker.h +115 -0
  164. cyfaust/resources/architecture/faust/dsp/dsp-combiner.h +810 -0
  165. cyfaust/resources/architecture/faust/dsp/dsp-compute-adapter.h +159 -0
  166. cyfaust/resources/architecture/faust/dsp/dsp-multi.h +702 -0
  167. cyfaust/resources/architecture/faust/dsp/dsp-multifun.h +90 -0
  168. cyfaust/resources/architecture/faust/dsp/dsp-optimizer.h +511 -0
  169. cyfaust/resources/architecture/faust/dsp/dsp-tools.h +229 -0
  170. cyfaust/resources/architecture/faust/dsp/dsp.h +321 -0
  171. cyfaust/resources/architecture/faust/dsp/fastmath.cpp +301 -0
  172. cyfaust/resources/architecture/faust/dsp/faust-dynamic-engine.cpp +494 -0
  173. cyfaust/resources/architecture/faust/dsp/faust-dynamic-engine.h +386 -0
  174. cyfaust/resources/architecture/faust/dsp/faust-engine.h +75 -0
  175. cyfaust/resources/architecture/faust/dsp/faust-poly-engine.h +638 -0
  176. cyfaust/resources/architecture/faust/dsp/interpreter-dsp-c.h +288 -0
  177. cyfaust/resources/architecture/faust/dsp/interpreter-dsp.h +362 -0
  178. cyfaust/resources/architecture/faust/dsp/interpreter-machine-dsp.h +233 -0
  179. cyfaust/resources/architecture/faust/dsp/libfaust-box-c.h +817 -0
  180. cyfaust/resources/architecture/faust/dsp/libfaust-box.h +889 -0
  181. cyfaust/resources/architecture/faust/dsp/libfaust-c.h +116 -0
  182. cyfaust/resources/architecture/faust/dsp/libfaust-signal-c.h +649 -0
  183. cyfaust/resources/architecture/faust/dsp/libfaust-signal.h +731 -0
  184. cyfaust/resources/architecture/faust/dsp/llvm-dsp-adapter.h +160 -0
  185. cyfaust/resources/architecture/faust/dsp/llvm-dsp-c.h +524 -0
  186. cyfaust/resources/architecture/faust/dsp/llvm-dsp.h +575 -0
  187. cyfaust/resources/architecture/faust/dsp/llvm-machine-dsp.h +215 -0
  188. cyfaust/resources/architecture/faust/dsp/one-sample-dsp.h +477 -0
  189. cyfaust/resources/architecture/faust/dsp/poly-dsp.h +1079 -0
  190. cyfaust/resources/architecture/faust/dsp/poly-interpreter-dsp.h +143 -0
  191. cyfaust/resources/architecture/faust/dsp/poly-llvm-dsp.h +249 -0
  192. cyfaust/resources/architecture/faust/dsp/poly-wasm-dsp.h +257 -0
  193. cyfaust/resources/architecture/faust/dsp/proxy-dsp.h +108 -0
  194. cyfaust/resources/architecture/faust/dsp/proxy-osc-dsp.h +109 -0
  195. cyfaust/resources/architecture/faust/dsp/rnbo-dsp.h +187 -0
  196. cyfaust/resources/architecture/faust/dsp/sound-player.h +428 -0
  197. cyfaust/resources/architecture/faust/dsp/timed-dsp.h +279 -0
  198. cyfaust/resources/architecture/faust/dsp/wasm-dsp-imp.h +188 -0
  199. cyfaust/resources/architecture/faust/dsp/wasm-dsp.h +309 -0
  200. cyfaust/resources/architecture/faust/dsp/ysfx-dsp.h +188 -0
  201. cyfaust/resources/architecture/faust/export.h +61 -0
  202. cyfaust/resources/architecture/faust/gui/APIUI.h +726 -0
  203. cyfaust/resources/architecture/faust/gui/BelaOSCUI.h +170 -0
  204. cyfaust/resources/architecture/faust/gui/CGlue.h +667 -0
  205. cyfaust/resources/architecture/faust/gui/CInterface.h +142 -0
  206. cyfaust/resources/architecture/faust/gui/ControlSequenceUI.h +197 -0
  207. cyfaust/resources/architecture/faust/gui/ControlUI.h +137 -0
  208. cyfaust/resources/architecture/faust/gui/DaisyControlUI.h +283 -0
  209. cyfaust/resources/architecture/faust/gui/DaisyPatchInitControlUI.h +254 -0
  210. cyfaust/resources/architecture/faust/gui/DecoratorUI.h +115 -0
  211. cyfaust/resources/architecture/faust/gui/Esp32ControlUI.h +341 -0
  212. cyfaust/resources/architecture/faust/gui/Esp32Reader.h +102 -0
  213. cyfaust/resources/architecture/faust/gui/Esp32SensorUI.h +137 -0
  214. cyfaust/resources/architecture/faust/gui/FUI.h +147 -0
  215. cyfaust/resources/architecture/faust/gui/GTKUI.h +1414 -0
  216. cyfaust/resources/architecture/faust/gui/GUI.h +465 -0
  217. cyfaust/resources/architecture/faust/gui/JSONControl.h +48 -0
  218. cyfaust/resources/architecture/faust/gui/JSONUI.h +722 -0
  219. cyfaust/resources/architecture/faust/gui/JSONUIDecoder.h +589 -0
  220. cyfaust/resources/architecture/faust/gui/JuceGUI.h +2061 -0
  221. cyfaust/resources/architecture/faust/gui/JuceOSCUI.h +163 -0
  222. cyfaust/resources/architecture/faust/gui/JuceParameterUI.h +158 -0
  223. cyfaust/resources/architecture/faust/gui/JuceReader.h +103 -0
  224. cyfaust/resources/architecture/faust/gui/JuceStateUI.h +88 -0
  225. cyfaust/resources/architecture/faust/gui/LayoutUI.h +423 -0
  226. cyfaust/resources/architecture/faust/gui/LibsndfileReader.h +366 -0
  227. cyfaust/resources/architecture/faust/gui/MapUI.h +370 -0
  228. cyfaust/resources/architecture/faust/gui/MemoryReader.h +111 -0
  229. cyfaust/resources/architecture/faust/gui/MetaDataUI.h +357 -0
  230. cyfaust/resources/architecture/faust/gui/MidiUI.h +939 -0
  231. cyfaust/resources/architecture/faust/gui/OCVUI.h +688 -0
  232. cyfaust/resources/architecture/faust/gui/OSCUI.h +219 -0
  233. cyfaust/resources/architecture/faust/gui/PathBuilder.h +228 -0
  234. cyfaust/resources/architecture/faust/gui/PresetUI.h +337 -0
  235. cyfaust/resources/architecture/faust/gui/PrintCUI.h +152 -0
  236. cyfaust/resources/architecture/faust/gui/PrintUI.h +121 -0
  237. cyfaust/resources/architecture/faust/gui/QTUI.h +1891 -0
  238. cyfaust/resources/architecture/faust/gui/RosCI.h +493 -0
  239. cyfaust/resources/architecture/faust/gui/RosUI.h +488 -0
  240. cyfaust/resources/architecture/faust/gui/SaveUI.h +163 -0
  241. cyfaust/resources/architecture/faust/gui/SimpleParser.h +583 -0
  242. cyfaust/resources/architecture/faust/gui/SoundUI.h +217 -0
  243. cyfaust/resources/architecture/faust/gui/Soundfile.h +342 -0
  244. cyfaust/resources/architecture/faust/gui/Styles/Blue.qrc +5 -0
  245. cyfaust/resources/architecture/faust/gui/Styles/Blue.qss +177 -0
  246. cyfaust/resources/architecture/faust/gui/Styles/Default.qrc +5 -0
  247. cyfaust/resources/architecture/faust/gui/Styles/Default.qss +117 -0
  248. cyfaust/resources/architecture/faust/gui/Styles/Grey.qrc +5 -0
  249. cyfaust/resources/architecture/faust/gui/Styles/Grey.qss +174 -0
  250. cyfaust/resources/architecture/faust/gui/Styles/Salmon.qrc +5 -0
  251. cyfaust/resources/architecture/faust/gui/Styles/Salmon.qss +171 -0
  252. cyfaust/resources/architecture/faust/gui/UI.h +87 -0
  253. cyfaust/resources/architecture/faust/gui/ValueConverter.h +543 -0
  254. cyfaust/resources/architecture/faust/gui/WaveReader.h +364 -0
  255. cyfaust/resources/architecture/faust/gui/console.h +322 -0
  256. cyfaust/resources/architecture/faust/gui/httpdUI.h +372 -0
  257. cyfaust/resources/architecture/faust/gui/meta.h +39 -0
  258. cyfaust/resources/architecture/faust/gui/mspUI.h +580 -0
  259. cyfaust/resources/architecture/faust/gui/qrcodegen.h +269 -0
  260. cyfaust/resources/architecture/faust/gui/qrcodegen.impl.h +1025 -0
  261. cyfaust/resources/architecture/faust/gui/ring-buffer.h +414 -0
  262. cyfaust/resources/architecture/faust/midi/RtMidi.cpp +3054 -0
  263. cyfaust/resources/architecture/faust/midi/RtMidi.h +1034 -0
  264. cyfaust/resources/architecture/faust/midi/bela-midi.h +266 -0
  265. cyfaust/resources/architecture/faust/midi/daisy-midi.h +116 -0
  266. cyfaust/resources/architecture/faust/midi/esp32-midi.h +185 -0
  267. cyfaust/resources/architecture/faust/midi/gramophone-midi.h +107 -0
  268. cyfaust/resources/architecture/faust/midi/iplug2-midi.h +148 -0
  269. cyfaust/resources/architecture/faust/midi/jack-midi.h +247 -0
  270. cyfaust/resources/architecture/faust/midi/juce-midi.h +275 -0
  271. cyfaust/resources/architecture/faust/midi/midi.h +475 -0
  272. cyfaust/resources/architecture/faust/midi/rt-midi.h +315 -0
  273. cyfaust/resources/architecture/faust/midi/teensy-midi.h +89 -0
  274. cyfaust/resources/architecture/faust/misc.h +106 -0
  275. cyfaust/resources/architecture/faust/sound-file.h +132 -0
  276. cyfaust/resources/architecture/faust/unity/AudioPluginInterface.h +301 -0
  277. cyfaust/resources/architecture/faust/vst/faust.h +141 -0
  278. cyfaust/resources/architecture/faust/vst/voice.h +43 -0
  279. cyfaust/resources/architecture/faust/vst/vstui.h +524 -0
  280. cyfaust/resources/architecture/faustvst.cpp +3435 -0
  281. cyfaust/resources/architecture/faustvstqt.h +91 -0
  282. cyfaust/resources/architecture/gen-json.cpp +76 -0
  283. cyfaust/resources/architecture/jack-console.cpp +267 -0
  284. cyfaust/resources/architecture/jack-gtk-ros.cpp +139 -0
  285. cyfaust/resources/architecture/jack-gtk.cpp +282 -0
  286. cyfaust/resources/architecture/jack-internal.cpp +560 -0
  287. cyfaust/resources/architecture/jack-qt-chain-footer.cpp +87 -0
  288. cyfaust/resources/architecture/jack-qt-chain-header.cpp +92 -0
  289. cyfaust/resources/architecture/jack-qt.cpp +281 -0
  290. cyfaust/resources/architecture/jack.rs +171 -0
  291. cyfaust/resources/architecture/juce/README.md +84 -0
  292. cyfaust/resources/architecture/juce/juce-plugin.cpp +809 -0
  293. cyfaust/resources/architecture/juce/juce-standalone.cpp +413 -0
  294. cyfaust/resources/architecture/juce/plugin/plugin-llvm.jucer +184 -0
  295. cyfaust/resources/architecture/juce/plugin/plugin.jucer +159 -0
  296. cyfaust/resources/architecture/juce/standalone/standalone-llvm.jucer +216 -0
  297. cyfaust/resources/architecture/juce/standalone/standalone.jucer +191 -0
  298. cyfaust/resources/architecture/ladspa.cpp +543 -0
  299. cyfaust/resources/architecture/latexheader.tex +65 -0
  300. cyfaust/resources/architecture/lv2.cpp +2090 -0
  301. cyfaust/resources/architecture/lv2qtgui.h +62 -0
  302. cyfaust/resources/architecture/lv2ui.cpp +1966 -0
  303. cyfaust/resources/architecture/max-msp/README.md +109 -0
  304. cyfaust/resources/architecture/max-msp/faustgen-wrapper-poly.maxpat +184 -0
  305. cyfaust/resources/architecture/max-msp/faustgen-wrapper.maxpat +163 -0
  306. cyfaust/resources/architecture/max-msp/max-msp.cpp +734 -0
  307. cyfaust/resources/architecture/max-msp/max-msp64.cpp +789 -0
  308. cyfaust/resources/architecture/max-msp/py2max/README.md +277 -0
  309. cyfaust/resources/architecture/max-msp/py2max/py2max/__init__.py +3 -0
  310. cyfaust/resources/architecture/max-msp/py2max/py2max/common.py +7 -0
  311. cyfaust/resources/architecture/max-msp/py2max/py2max/core.py +1387 -0
  312. cyfaust/resources/architecture/max-msp/py2max/py2max/maxclassdb.py +318 -0
  313. cyfaust/resources/architecture/max-msp/py2max/py2max/utils.py +20 -0
  314. cyfaust/resources/architecture/max-msp/rnbo.py +1591 -0
  315. cyfaust/resources/architecture/max-msp/sndfile/sndfile.h +857 -0
  316. cyfaust/resources/architecture/max-msp/ui.js +230 -0
  317. cyfaust/resources/architecture/max-msp/wrapper-poly.maxpat +153 -0
  318. cyfaust/resources/architecture/max-msp/wrapper.maxpat +131 -0
  319. cyfaust/resources/architecture/minimal-bench.cpp +100 -0
  320. cyfaust/resources/architecture/minimal-effect.c +149 -0
  321. cyfaust/resources/architecture/minimal-effect.cpp +70 -0
  322. cyfaust/resources/architecture/minimal-fixed-point.cpp +195 -0
  323. cyfaust/resources/architecture/minimal-static.cpp +160 -0
  324. cyfaust/resources/architecture/minimal.c +103 -0
  325. cyfaust/resources/architecture/minimal.cpp +84 -0
  326. cyfaust/resources/architecture/minimal.rs +223 -0
  327. cyfaust/resources/architecture/module.cpp +91 -0
  328. cyfaust/resources/architecture/octave.cpp +471 -0
  329. cyfaust/resources/architecture/oscio-gtk.cpp +115 -0
  330. cyfaust/resources/architecture/oscio-qt.cpp +121 -0
  331. cyfaust/resources/architecture/owl.cpp +345 -0
  332. cyfaust/resources/architecture/pa-gtk.cpp +119 -0
  333. cyfaust/resources/architecture/pa-qt.cpp +261 -0
  334. cyfaust/resources/architecture/path-printer.cpp +100 -0
  335. cyfaust/resources/architecture/plot.cpp +128 -0
  336. cyfaust/resources/architecture/portaudio.rs +192 -0
  337. cyfaust/resources/architecture/puredata.cpp +636 -0
  338. cyfaust/resources/architecture/ra-qt.cpp +238 -0
  339. cyfaust/resources/architecture/sam/fast_pow2.h +69 -0
  340. cyfaust/resources/architecture/sam/fastexp.h +140 -0
  341. cyfaust/resources/architecture/sam/samFaustDSP.cpp +125 -0
  342. cyfaust/resources/architecture/sam/samFaustDSP.h +107 -0
  343. cyfaust/resources/architecture/scheduler.cpp +1391 -0
  344. cyfaust/resources/architecture/sndfile.cpp +291 -0
  345. cyfaust/resources/architecture/supercollider.cpp +611 -0
  346. cyfaust/resources/architecture/teensy/README.md +13 -0
  347. cyfaust/resources/architecture/teensy/teensy.cpp +214 -0
  348. cyfaust/resources/architecture/teensy/teensy.h +71 -0
  349. cyfaust/resources/architecture/thread.h +373 -0
  350. cyfaust/resources/architecture/vcvrack/README.md +78 -0
  351. cyfaust/resources/architecture/vcvrack/template/.gitignore +6 -0
  352. cyfaust/resources/architecture/vcvrack/template/Makefile +22 -0
  353. cyfaust/resources/architecture/vcvrack/template/res/FaustModule.svg +299 -0
  354. cyfaust/resources/architecture/vcvrack/template/src/FaustModule.cpp +942 -0
  355. cyfaust/resources/architecture/vst.cpp +947 -0
  356. cyfaust/resources/libraries/aanl.lib +900 -0
  357. cyfaust/resources/libraries/all.lib +36 -0
  358. cyfaust/resources/libraries/analyzers.lib +980 -0
  359. cyfaust/resources/libraries/basics.lib +2681 -0
  360. cyfaust/resources/libraries/compressors.lib +1341 -0
  361. cyfaust/resources/libraries/delays.lib +401 -0
  362. cyfaust/resources/libraries/demos.lib +1556 -0
  363. cyfaust/resources/libraries/dx7.lib +1036 -0
  364. cyfaust/resources/libraries/effect.lib +1645 -0
  365. cyfaust/resources/libraries/envelopes.lib +666 -0
  366. cyfaust/resources/libraries/examples/README.md +13 -0
  367. cyfaust/resources/libraries/examples/ambisonics/fourSourcesToOcto.dsp +20 -0
  368. cyfaust/resources/libraries/examples/ambisonics/oneSourceToStereo.dsp +12 -0
  369. cyfaust/resources/libraries/examples/analysis/FFT.dsp +26 -0
  370. cyfaust/resources/libraries/examples/analysis/dbmeter.dsp +19 -0
  371. cyfaust/resources/libraries/examples/analysis/spectralLevel.dsp +8 -0
  372. cyfaust/resources/libraries/examples/analysis/spectralTiltLab.dsp +20 -0
  373. cyfaust/resources/libraries/examples/analysis/vumeter.dsp +18 -0
  374. cyfaust/resources/libraries/examples/autodiff/delay/diff.dsp +2 -0
  375. cyfaust/resources/libraries/examples/autodiff/delay/gt.dsp +2 -0
  376. cyfaust/resources/libraries/examples/autodiff/gain/diff.dsp +7 -0
  377. cyfaust/resources/libraries/examples/autodiff/gain/gt.dsp +1 -0
  378. cyfaust/resources/libraries/examples/autodiff/gain_dc/diff.dsp +7 -0
  379. cyfaust/resources/libraries/examples/autodiff/gain_dc/gt.dsp +4 -0
  380. cyfaust/resources/libraries/examples/autodiff/gain_exp/diff.dsp +9 -0
  381. cyfaust/resources/libraries/examples/autodiff/gain_exp/gt.dsp +1 -0
  382. cyfaust/resources/libraries/examples/autodiff/gain_pow/diff.dsp +9 -0
  383. cyfaust/resources/libraries/examples/autodiff/gain_pow/gt.dsp +1 -0
  384. cyfaust/resources/libraries/examples/autodiff/gain_pow_trig/diff.dsp +12 -0
  385. cyfaust/resources/libraries/examples/autodiff/gain_pow_trig/gt.dsp +1 -0
  386. cyfaust/resources/libraries/examples/autodiff/gain_sq/diff.dsp +7 -0
  387. cyfaust/resources/libraries/examples/autodiff/gain_sq/gt.dsp +1 -0
  388. cyfaust/resources/libraries/examples/autodiff/mem/diff.dsp +1 -0
  389. cyfaust/resources/libraries/examples/autodiff/mem/gt.dsp +1 -0
  390. cyfaust/resources/libraries/examples/autodiff/noise.dsp +2 -0
  391. cyfaust/resources/libraries/examples/autodiff/noop.dsp +2 -0
  392. cyfaust/resources/libraries/examples/autodiff/one_zero/diff.dsp +2 -0
  393. cyfaust/resources/libraries/examples/autodiff/one_zero/gt.dsp +2 -0
  394. cyfaust/resources/libraries/examples/autodiff/ramp.dsp +1 -0
  395. cyfaust/resources/libraries/examples/autodiff/recursion/diff.dsp +2 -0
  396. cyfaust/resources/libraries/examples/autodiff/recursion/gt.dsp +1 -0
  397. cyfaust/resources/libraries/examples/autodiff/recursion/target.dsp +13 -0
  398. cyfaust/resources/libraries/examples/autodiff/tremolo/diff.dsp +14 -0
  399. cyfaust/resources/libraries/examples/autodiff/tremolo/diffable.lib +7 -0
  400. cyfaust/resources/libraries/examples/autodiff/tremolo/gt.dsp +11 -0
  401. cyfaust/resources/libraries/examples/delayEcho/echo.dsp +15 -0
  402. cyfaust/resources/libraries/examples/delayEcho/quadEcho.dsp +21 -0
  403. cyfaust/resources/libraries/examples/delayEcho/smoothDelay.dsp +26 -0
  404. cyfaust/resources/libraries/examples/delayEcho/stereoEcho.dsp +16 -0
  405. cyfaust/resources/libraries/examples/delayEcho/tapiir.dsp +44 -0
  406. cyfaust/resources/libraries/examples/dynamic/compressor.dsp +8 -0
  407. cyfaust/resources/libraries/examples/dynamic/distortion.dsp +8 -0
  408. cyfaust/resources/libraries/examples/dynamic/gateCompressor.dsp +10 -0
  409. cyfaust/resources/libraries/examples/dynamic/noiseGate.dsp +8 -0
  410. cyfaust/resources/libraries/examples/dynamic/volume.dsp +15 -0
  411. cyfaust/resources/libraries/examples/filtering/APF.dsp +13 -0
  412. cyfaust/resources/libraries/examples/filtering/BPF.dsp +13 -0
  413. cyfaust/resources/libraries/examples/filtering/DNN.dsp +25 -0
  414. cyfaust/resources/libraries/examples/filtering/HPF.dsp +13 -0
  415. cyfaust/resources/libraries/examples/filtering/LPF.dsp +13 -0
  416. cyfaust/resources/libraries/examples/filtering/bandFilter.dsp +44 -0
  417. cyfaust/resources/libraries/examples/filtering/cryBaby.dsp +4 -0
  418. cyfaust/resources/libraries/examples/filtering/diodeLadder.dsp +12 -0
  419. cyfaust/resources/libraries/examples/filtering/filterBank.dsp +6 -0
  420. cyfaust/resources/libraries/examples/filtering/graphicEqLab.dsp +10 -0
  421. cyfaust/resources/libraries/examples/filtering/highShelf.dsp +13 -0
  422. cyfaust/resources/libraries/examples/filtering/korg35HPF.dsp +13 -0
  423. cyfaust/resources/libraries/examples/filtering/korg35LPF.dsp +13 -0
  424. cyfaust/resources/libraries/examples/filtering/lfBoost.dsp +40 -0
  425. cyfaust/resources/libraries/examples/filtering/lowBoost.dsp +40 -0
  426. cyfaust/resources/libraries/examples/filtering/lowCut.dsp +40 -0
  427. cyfaust/resources/libraries/examples/filtering/lowShelf.dsp +13 -0
  428. cyfaust/resources/libraries/examples/filtering/moogHalfLadder.dsp +12 -0
  429. cyfaust/resources/libraries/examples/filtering/moogLadder.dsp +12 -0
  430. cyfaust/resources/libraries/examples/filtering/moogVCF.dsp +6 -0
  431. cyfaust/resources/libraries/examples/filtering/multibandFilter.dsp +14 -0
  432. cyfaust/resources/libraries/examples/filtering/notch.dsp +13 -0
  433. cyfaust/resources/libraries/examples/filtering/oberheim.dsp +14 -0
  434. cyfaust/resources/libraries/examples/filtering/oberheimBPF.dsp +13 -0
  435. cyfaust/resources/libraries/examples/filtering/oberheimBSF.dsp +13 -0
  436. cyfaust/resources/libraries/examples/filtering/oberheimHPF.dsp +13 -0
  437. cyfaust/resources/libraries/examples/filtering/oberheimLPF.dsp +13 -0
  438. cyfaust/resources/libraries/examples/filtering/parametricEqLab.dsp +10 -0
  439. cyfaust/resources/libraries/examples/filtering/parametricEqualizer.dsp +6 -0
  440. cyfaust/resources/libraries/examples/filtering/peakNotch.dsp +13 -0
  441. cyfaust/resources/libraries/examples/filtering/peakingEQ.dsp +13 -0
  442. cyfaust/resources/libraries/examples/filtering/sallenKey2ndOrder.dsp +14 -0
  443. cyfaust/resources/libraries/examples/filtering/sallenKey2ndOrderBPF.dsp +13 -0
  444. cyfaust/resources/libraries/examples/filtering/sallenKey2ndOrderHPF.dsp +13 -0
  445. cyfaust/resources/libraries/examples/filtering/sallenKey2ndOrderLPF.dsp +13 -0
  446. cyfaust/resources/libraries/examples/filtering/sallenKeyOnePole.dsp +13 -0
  447. cyfaust/resources/libraries/examples/filtering/sallenKeyOnePoleHPF.dsp +12 -0
  448. cyfaust/resources/libraries/examples/filtering/sallenKeyOnePoleLPF.dsp +12 -0
  449. cyfaust/resources/libraries/examples/filtering/spectralTilt.dsp +8 -0
  450. cyfaust/resources/libraries/examples/filtering/vcfWahLab.dsp +12 -0
  451. cyfaust/resources/libraries/examples/filtering/vocoder.dsp +8 -0
  452. cyfaust/resources/libraries/examples/filtering/wahPedal.dsp +6 -0
  453. cyfaust/resources/libraries/examples/gameaudio/bubble.dsp +42 -0
  454. cyfaust/resources/libraries/examples/gameaudio/door.dsp +58 -0
  455. cyfaust/resources/libraries/examples/gameaudio/fire.dsp +46 -0
  456. cyfaust/resources/libraries/examples/gameaudio/insects.dsp +148 -0
  457. cyfaust/resources/libraries/examples/gameaudio/rain.dsp +27 -0
  458. cyfaust/resources/libraries/examples/gameaudio/wind.dsp +23 -0
  459. cyfaust/resources/libraries/examples/generator/filterOsc.dsp +8 -0
  460. cyfaust/resources/libraries/examples/generator/noise.dsp +52 -0
  461. cyfaust/resources/libraries/examples/generator/noiseMetadata.dsp +74 -0
  462. cyfaust/resources/libraries/examples/generator/osc.dsp +17 -0
  463. cyfaust/resources/libraries/examples/generator/osci.dsp +17 -0
  464. cyfaust/resources/libraries/examples/generator/sawtoothLab.dsp +8 -0
  465. cyfaust/resources/libraries/examples/generator/virtualAnalog.dsp +8 -0
  466. cyfaust/resources/libraries/examples/generator/virtualAnalogLab.dsp +10 -0
  467. cyfaust/resources/libraries/examples/misc/UITester.dsp +71 -0
  468. cyfaust/resources/libraries/examples/misc/autopan.dsp +59 -0
  469. cyfaust/resources/libraries/examples/misc/capture.dsp +24 -0
  470. cyfaust/resources/libraries/examples/misc/drumkit.dsp +36 -0
  471. cyfaust/resources/libraries/examples/misc/guitarix.dsp +184 -0
  472. cyfaust/resources/libraries/examples/misc/matrix.dsp +17 -0
  473. cyfaust/resources/libraries/examples/misc/midiTester.dsp +122 -0
  474. cyfaust/resources/libraries/examples/misc/mixer.dsp +27 -0
  475. cyfaust/resources/libraries/examples/misc/statespace.dsp +39 -0
  476. cyfaust/resources/libraries/examples/misc/switcher.dsp +20 -0
  477. cyfaust/resources/libraries/examples/misc/tester.dsp +32 -0
  478. cyfaust/resources/libraries/examples/misc/tester2.dsp +31 -0
  479. cyfaust/resources/libraries/examples/old/README.md +5 -0
  480. cyfaust/resources/libraries/examples/old/freeverb.dsp +109 -0
  481. cyfaust/resources/libraries/examples/old/rewriting/Makefile +21 -0
  482. cyfaust/resources/libraries/examples/old/rewriting/fact.dsp +3 -0
  483. cyfaust/resources/libraries/examples/old/rewriting/fold.dsp +61 -0
  484. cyfaust/resources/libraries/examples/old/rewriting/mesh.dsp +43 -0
  485. cyfaust/resources/libraries/examples/old/rewriting/mesh.pd +37 -0
  486. cyfaust/resources/libraries/examples/old/rewriting/sample.pd +12 -0
  487. cyfaust/resources/libraries/examples/old/rewriting/serial.dsp +7 -0
  488. cyfaust/resources/libraries/examples/old/rewriting/sum.dsp +55 -0
  489. cyfaust/resources/libraries/examples/old/rewriting/test.pd +48 -0
  490. cyfaust/resources/libraries/examples/phasing/flanger.dsp +8 -0
  491. cyfaust/resources/libraries/examples/phasing/phaser.dsp +8 -0
  492. cyfaust/resources/libraries/examples/phasing/phaserFlangerLab.dsp +12 -0
  493. cyfaust/resources/libraries/examples/physicalModeling/brass.dsp +8 -0
  494. cyfaust/resources/libraries/examples/physicalModeling/brassMIDI.dsp +8 -0
  495. cyfaust/resources/libraries/examples/physicalModeling/churchBell.dsp +8 -0
  496. cyfaust/resources/libraries/examples/physicalModeling/clarinet.dsp +8 -0
  497. cyfaust/resources/libraries/examples/physicalModeling/clarinetMIDI.dsp +8 -0
  498. cyfaust/resources/libraries/examples/physicalModeling/djembeMIDI.dsp +8 -0
  499. cyfaust/resources/libraries/examples/physicalModeling/elecGuitarMIDI.dsp +10 -0
  500. cyfaust/resources/libraries/examples/physicalModeling/englishBell.dsp +8 -0
  501. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/NLFeks.dsp +91 -0
  502. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/NLFfm.dsp +70 -0
  503. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/README +125 -0
  504. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/bass.dsp +84 -0
  505. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/bass.h +91 -0
  506. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/blowBottle.dsp +102 -0
  507. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/bowed.dsp +114 -0
  508. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/brass.dsp +103 -0
  509. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/clarinet.dsp +110 -0
  510. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/flute.dsp +116 -0
  511. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/fluteStk.dsp +121 -0
  512. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/glassHarmonica.dsp +131 -0
  513. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/harpsi.dsp +90 -0
  514. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/harpsichord.h +185 -0
  515. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/instrument.h +114 -0
  516. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/modalBar.dsp +122 -0
  517. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/modalBar.h +48 -0
  518. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/audio-out.pd +33 -0
  519. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/bottle.pd +10 -0
  520. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/clarinets.pd +15 -0
  521. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/canon/audio-out.pd +33 -0
  522. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/canon/bass.pd +162 -0
  523. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/canon/canon.pd +55 -0
  524. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/canon/flute.pd +343 -0
  525. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/canon/pachelbel.mid +0 -0
  526. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/daisy/audio-out.pd +33 -0
  527. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/daisy/daisy.mid +0 -0
  528. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/daisy/daisy.pd +45 -0
  529. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/daisy/piano.pd +205 -0
  530. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/daisy/voiceForm.pd +340 -0
  531. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/take5/audio-out.pd +33 -0
  532. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/take5/blowHole.pd +330 -0
  533. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/take5/piano.pd +205 -0
  534. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/take5/take5.mid +0 -0
  535. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/take5/take5.pd +45 -0
  536. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/turkish-march/audio-out.pd +33 -0
  537. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/turkish-march/harpsi.pd +204 -0
  538. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/turkish-march/turkish-march.mid +0 -0
  539. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/turkish-march/turkish-march.pd +31 -0
  540. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/what-a-friend/audio-out.pd +33 -0
  541. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/what-a-friend/bass.pd +162 -0
  542. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/what-a-friend/modalBar.pd +258 -0
  543. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/what-a-friend/piano.pd +205 -0
  544. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/what-a-friend/what-a-friend.pd +52 -0
  545. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fancy/what-a-friend/what_a_friend.mid +0 -0
  546. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/flutes.pd +15 -0
  547. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/fm.pd +10 -0
  548. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/glassBare.pd +10 -0
  549. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/harpsichord-poly.pd +10 -0
  550. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/ironBare.pd +10 -0
  551. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/midi-in.pd +111 -0
  552. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/modal.pd +10 -0
  553. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/osc.pd +26 -0
  554. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/piano-poly.pd +10 -0
  555. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/plucked.pd +20 -0
  556. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/saxophone.pd +10 -0
  557. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/tibetan.pd +10 -0
  558. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/trumpet.pd +10 -0
  559. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/violin.pd +10 -0
  560. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/voiceSynth.pd +10 -0
  561. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/pd-patches/woodenBare.pd +10 -0
  562. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/phonemes.h +189 -0
  563. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/piano.dsp +255 -0
  564. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/piano.h +751 -0
  565. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/saxophony.dsp +114 -0
  566. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/sitar.dsp +48 -0
  567. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/tibetanBowl.dsp +155 -0
  568. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/tunedBar.dsp +123 -0
  569. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/uniBar.dsp +100 -0
  570. cyfaust/resources/libraries/examples/physicalModeling/faust-stk/voiceForm.dsp +125 -0
  571. cyfaust/resources/libraries/examples/physicalModeling/fds/1dDampedWaveEquation.dsp +43 -0
  572. cyfaust/resources/libraries/examples/physicalModeling/fds/2dKirchhoffThinPlate.dsp +75 -0
  573. cyfaust/resources/libraries/examples/physicalModeling/fds/BowedString.dsp +61 -0
  574. cyfaust/resources/libraries/examples/physicalModeling/fds/ControllableNonPhysicalString.dsp +72 -0
  575. cyfaust/resources/libraries/examples/physicalModeling/fds/HammeredString.dsp +74 -0
  576. cyfaust/resources/libraries/examples/physicalModeling/fds/PianoHammeredString.dsp +85 -0
  577. cyfaust/resources/libraries/examples/physicalModeling/fds/StiffString.dsp +54 -0
  578. cyfaust/resources/libraries/examples/physicalModeling/flute.dsp +8 -0
  579. cyfaust/resources/libraries/examples/physicalModeling/fluteMIDI.dsp +8 -0
  580. cyfaust/resources/libraries/examples/physicalModeling/frenchBell.dsp +8 -0
  581. cyfaust/resources/libraries/examples/physicalModeling/germanBell.dsp +8 -0
  582. cyfaust/resources/libraries/examples/physicalModeling/guitarMIDI.dsp +8 -0
  583. cyfaust/resources/libraries/examples/physicalModeling/karplus.dsp +8 -0
  584. cyfaust/resources/libraries/examples/physicalModeling/marimbaMIDI.dsp +10 -0
  585. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/00_BasicOscillator/harmonicOscillator.dsp +58 -0
  586. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/00_BasicOscillator/harmonicOscillator2.dsp +62 -0
  587. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/00_BasicOscillator/harmonicOscillator3.dsp +65 -0
  588. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/01_ParamControl/paramOsc.dsp +63 -0
  589. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/02_AudioParamControl/audioParamOsc.dsp +63 -0
  590. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/03_HammerTime/hammerOsc.dsp +71 -0
  591. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/04_Gravity/bouncingOsc.dsp +64 -0
  592. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/05_PluckedOscillator/pluckedOsc.dsp +57 -0
  593. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/06_BowedOscillator/bowedOsc.dsp +65 -0
  594. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/07_NonLinearOscillator/nlOsc.dsp +78 -0
  595. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/08_TwoMassChain/2massChain.dsp +75 -0
  596. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/09_TinyString/tinyString.dsp +101 -0
  597. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/10_PluckedString/pluckedString.dsp +678 -0
  598. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/11_BowedString/bowedString.dsp +671 -0
  599. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/12_TriangleMesh/triangleMesh.dsp +448 -0
  600. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/13_Construction/construction.dsp +1036 -0
  601. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/14_Polyphonic/polyTriangle.dsp +79 -0
  602. cyfaust/resources/libraries/examples/physicalModeling/mi-faust/15_PhysicalLFO/physicalLFO.dsp +107 -0
  603. cyfaust/resources/libraries/examples/physicalModeling/modularInterpInstrMIDI.dsp +8 -0
  604. cyfaust/resources/libraries/examples/physicalModeling/nylonGuitarMIDI.dsp +8 -0
  605. cyfaust/resources/libraries/examples/physicalModeling/old/harpe.dsp +45 -0
  606. cyfaust/resources/libraries/examples/physicalModeling/old/karplus.dsp +34 -0
  607. cyfaust/resources/libraries/examples/physicalModeling/old/karplus32.dsp +47 -0
  608. cyfaust/resources/libraries/examples/physicalModeling/russianBell.dsp +8 -0
  609. cyfaust/resources/libraries/examples/physicalModeling/standardBell.dsp +8 -0
  610. cyfaust/resources/libraries/examples/physicalModeling/violin.dsp +8 -0
  611. cyfaust/resources/libraries/examples/physicalModeling/violinMIDI.dsp +8 -0
  612. cyfaust/resources/libraries/examples/physicalModeling/vocalBP.dsp +8 -0
  613. cyfaust/resources/libraries/examples/physicalModeling/vocalBPMIDI.dsp +8 -0
  614. cyfaust/resources/libraries/examples/physicalModeling/vocalFOF.dsp +8 -0
  615. cyfaust/resources/libraries/examples/physicalModeling/vocalFOFMIDI.dsp +8 -0
  616. cyfaust/resources/libraries/examples/pitchShifting/pitchShifter.dsp +20 -0
  617. cyfaust/resources/libraries/examples/psychoacoustic/harmonicExciter.dsp +10 -0
  618. cyfaust/resources/libraries/examples/quantizing/quantizedChords.dsp +49 -0
  619. cyfaust/resources/libraries/examples/reverb/dattorro.dsp +8 -0
  620. cyfaust/resources/libraries/examples/reverb/fdnRev.dsp +8 -0
  621. cyfaust/resources/libraries/examples/reverb/freeverb.dsp +8 -0
  622. cyfaust/resources/libraries/examples/reverb/greyhole.dsp +8 -0
  623. cyfaust/resources/libraries/examples/reverb/jprev.dsp +8 -0
  624. cyfaust/resources/libraries/examples/reverb/reverbDesigner.dsp +12 -0
  625. cyfaust/resources/libraries/examples/reverb/reverbTester.dsp +8 -0
  626. cyfaust/resources/libraries/examples/reverb/zitaRev.dsp +8 -0
  627. cyfaust/resources/libraries/examples/reverb/zitaRevFDN.dsp +8 -0
  628. cyfaust/resources/libraries/examples/smartKeyboard/acGuitar.dsp +100 -0
  629. cyfaust/resources/libraries/examples/smartKeyboard/associatedEffects/elecGuitarEffect.dsp +8 -0
  630. cyfaust/resources/libraries/examples/smartKeyboard/associatedEffects/myEffect.dsp +5 -0
  631. cyfaust/resources/libraries/examples/smartKeyboard/associatedEffects/reverb.dsp +5 -0
  632. cyfaust/resources/libraries/examples/smartKeyboard/bells.dsp +80 -0
  633. cyfaust/resources/libraries/examples/smartKeyboard/bowed.dsp +87 -0
  634. cyfaust/resources/libraries/examples/smartKeyboard/brass.dsp +82 -0
  635. cyfaust/resources/libraries/examples/smartKeyboard/clarinet.dsp +113 -0
  636. cyfaust/resources/libraries/examples/smartKeyboard/crazyGuiro.dsp +96 -0
  637. cyfaust/resources/libraries/examples/smartKeyboard/drums.dsp +74 -0
  638. cyfaust/resources/libraries/examples/smartKeyboard/dubDub.dsp +87 -0
  639. cyfaust/resources/libraries/examples/smartKeyboard/elecGuitar.dsp +67 -0
  640. cyfaust/resources/libraries/examples/smartKeyboard/fm.dsp +78 -0
  641. cyfaust/resources/libraries/examples/smartKeyboard/frog.dsp +74 -0
  642. cyfaust/resources/libraries/examples/smartKeyboard/harp.dsp +84 -0
  643. cyfaust/resources/libraries/examples/smartKeyboard/midiOnly.dsp +62 -0
  644. cyfaust/resources/libraries/examples/smartKeyboard/multiSynth.dsp +75 -0
  645. cyfaust/resources/libraries/examples/smartKeyboard/toy.dsp +71 -0
  646. cyfaust/resources/libraries/examples/smartKeyboard/trumpet.dsp +59 -0
  647. cyfaust/resources/libraries/examples/smartKeyboard/turenas.dsp +114 -0
  648. cyfaust/resources/libraries/examples/smartKeyboard/violin.dsp +91 -0
  649. cyfaust/resources/libraries/examples/smartKeyboard/violin2.dsp +84 -0
  650. cyfaust/resources/libraries/examples/smartKeyboard/vocal.dsp +43 -0
  651. cyfaust/resources/libraries/examples/spat/panpot.dsp +17 -0
  652. cyfaust/resources/libraries/examples/spat/spat.dsp +25 -0
  653. cyfaust/resources/libraries/fds.lib +535 -0
  654. cyfaust/resources/libraries/filter.lib +1710 -0
  655. cyfaust/resources/libraries/filters.lib +3125 -0
  656. cyfaust/resources/libraries/hoa.lib +1081 -0
  657. cyfaust/resources/libraries/instruments.lib +263 -0
  658. cyfaust/resources/libraries/interpolators.lib +675 -0
  659. cyfaust/resources/libraries/math.lib +602 -0
  660. cyfaust/resources/libraries/maths.lib +798 -0
  661. cyfaust/resources/libraries/maxmsp.lib +237 -0
  662. cyfaust/resources/libraries/mi.lib +528 -0
  663. cyfaust/resources/libraries/misceffects.lib +998 -0
  664. cyfaust/resources/libraries/music.lib +496 -0
  665. cyfaust/resources/libraries/noises.lib +487 -0
  666. cyfaust/resources/libraries/oscillator.lib +450 -0
  667. cyfaust/resources/libraries/oscillators.lib +1838 -0
  668. cyfaust/resources/libraries/phaflangers.lib +235 -0
  669. cyfaust/resources/libraries/physmodels.lib +3990 -0
  670. cyfaust/resources/libraries/platform.lib +59 -0
  671. cyfaust/resources/libraries/quantizers.lib +310 -0
  672. cyfaust/resources/libraries/reducemaps.lib +235 -0
  673. cyfaust/resources/libraries/reverbs.lib +686 -0
  674. cyfaust/resources/libraries/routes.lib +262 -0
  675. cyfaust/resources/libraries/sf.lib +53 -0
  676. cyfaust/resources/libraries/signals.lib +570 -0
  677. cyfaust/resources/libraries/soundfiles.lib +234 -0
  678. cyfaust/resources/libraries/spats.lib +173 -0
  679. cyfaust/resources/libraries/stdfaust.lib +38 -0
  680. cyfaust/resources/libraries/synths.lib +322 -0
  681. cyfaust/resources/libraries/tonestacks.lib +427 -0
  682. cyfaust/resources/libraries/tubes.lib +5039 -0
  683. cyfaust/resources/libraries/vaeffects.lib +984 -0
  684. cyfaust/resources/libraries/version.lib +22 -0
  685. cyfaust/resources/libraries/wdmodels.lib +2276 -0
  686. cyfaust/resources/libraries/webaudio.lib +402 -0
  687. cyfaust/signal.pxd +44 -0
  688. cyfaust/signal.pyx +1993 -0
  689. cyfaust-0.1.0.dist-info/METADATA +355 -0
  690. cyfaust-0.1.0.dist-info/RECORD +693 -0
  691. cyfaust-0.1.0.dist-info/WHEEL +5 -0
  692. cyfaust-0.1.0.dist-info/entry_points.txt +3 -0
  693. cyfaust-0.1.0.dist-info/licenses/LICENSE +26 -0
@@ -0,0 +1,3435 @@
1
+ /************************************************************************
2
+ ************************************************************************
3
+ FAUST Architecture File
4
+ Copyright (C) 2014-2016 Albert Graef <aggraef@gmail.com>
5
+ ---------------------------------------------------------------------
6
+ This program is free software; you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as
8
+ published by the Free Software Foundation; either version 3 of the
9
+ 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 Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public
17
+ License along with the GNU C Library; if not, write to the Free
18
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
+ 02111-1307 USA.
20
+ ************************************************************************
21
+ ************************************************************************/
22
+
23
+ /* VST architecture for Faust synths. */
24
+
25
+ /* NOTE: This requires one of the Boost headers (boost/circular_buffer.hpp),
26
+ so to compile Faust programs created with this architecture you need to
27
+ have at least the Boost headers installed somewhere on your include path
28
+ (the Boost libraries aren't needed). */
29
+
30
+ #include <cstdlib>
31
+ #include <cstdint>
32
+ #include <cmath>
33
+ #include <list>
34
+ #include <map>
35
+ #include <set>
36
+
37
+ // Generic Faust dsp and UI classes
38
+ #include <faust/dsp/dsp.h>
39
+ #include <faust/gui/UI.h>
40
+ #include <faust/gui/MidiUI.h>
41
+
42
+ using namespace std;
43
+
44
+ typedef pair<const char*,const char*> strpair;
45
+
46
+ struct MyMeta : Meta, std::map<const char*, const char*>
47
+ {
48
+ void declare(const char *key, const char *value)
49
+ {
50
+ (*this)[key] = value;
51
+ }
52
+
53
+ const char* get(const char *key, const char *def)
54
+ {
55
+ if (this->find(key) != this->end()) {
56
+ return (*this)[key];
57
+ } else {
58
+ return def;
59
+ }
60
+ }
61
+ };
62
+
63
+ /******************************************************************************
64
+ *******************************************************************************
65
+
66
+ VECTOR INTRINSICS
67
+
68
+ *******************************************************************************
69
+ *******************************************************************************/
70
+
71
+ <<includeIntrinsic>>
72
+
73
+ /***************************************************************************
74
+ VST UI interface
75
+ ***************************************************************************/
76
+
77
+ #include <string.h>
78
+
79
+ enum ui_elem_type_t {
80
+ UI_BUTTON, UI_CHECK_BUTTON,
81
+ UI_V_SLIDER, UI_H_SLIDER, UI_NUM_ENTRY,
82
+ UI_V_BARGRAPH, UI_H_BARGRAPH,
83
+ UI_END_GROUP, UI_V_GROUP, UI_H_GROUP, UI_T_GROUP
84
+ };
85
+
86
+ struct ui_elem_t {
87
+ ui_elem_type_t type;
88
+ const char *label;
89
+ int port;
90
+ float *zone;
91
+ void *ref;
92
+ float init, min, max, step;
93
+ };
94
+
95
+ class VSTUI : public UI
96
+ {
97
+ public:
98
+ bool is_instr;
99
+ int nelems, nports;
100
+ ui_elem_t *elems;
101
+ map< int, list<strpair> > metadata;
102
+
103
+ VSTUI(int maxvoices = 0);
104
+ virtual ~VSTUI();
105
+
106
+ protected:
107
+ void add_elem(ui_elem_type_t type, const char *label = NULL);
108
+ void add_elem(ui_elem_type_t type, const char *label, float *zone);
109
+ void add_elem(ui_elem_type_t type, const char *label, float *zone,
110
+ float init, float min, float max, float step);
111
+ void add_elem(ui_elem_type_t type, const char *label, float *zone,
112
+ float min, float max);
113
+
114
+ bool have_freq, have_gain, have_gate;
115
+ bool is_voice_ctrl(const char *label);
116
+
117
+ public:
118
+ virtual void addButton(const char* label, float* zone);
119
+ virtual void addCheckButton(const char* label, float* zone);
120
+ virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step);
121
+ virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step);
122
+ virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step);
123
+
124
+ virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max);
125
+ virtual void addVerticalBargraph(const char* label, float* zone, float min, float max);
126
+ virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
127
+
128
+ virtual void openTabBox(const char* label);
129
+ virtual void openHorizontalBox(const char* label);
130
+ virtual void openVerticalBox(const char* label);
131
+ virtual void closeBox();
132
+
133
+ virtual void run();
134
+
135
+ virtual void declare(float* zone, const char* key, const char* value);
136
+ };
137
+
138
+ VSTUI::VSTUI(int maxvoices)
139
+ {
140
+ is_instr = maxvoices>0;
141
+ have_freq = have_gain = have_gate = false;
142
+ nelems = nports = 0;
143
+ elems = NULL;
144
+ }
145
+
146
+ VSTUI::~VSTUI()
147
+ {
148
+ if (elems) free(elems);
149
+ }
150
+
151
+ void VSTUI::declare(float* zone, const char* key, const char* value)
152
+ {
153
+ map< int, list<strpair> >::iterator it = metadata.find(nelems);
154
+ if (it != metadata.end())
155
+ it->second.push_back(strpair(key, value));
156
+ else
157
+ metadata[nelems] = list<strpair>(1, strpair(key, value));
158
+ }
159
+
160
+ inline void VSTUI::add_elem(ui_elem_type_t type, const char *label)
161
+ {
162
+ ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
163
+ if (elems1)
164
+ elems = elems1;
165
+ else
166
+ return;
167
+ elems[nelems].type = type;
168
+ elems[nelems].label = label;
169
+ elems[nelems].port = -1;
170
+ elems[nelems].zone = NULL;
171
+ elems[nelems].ref = NULL;
172
+ elems[nelems].init = 0.0;
173
+ elems[nelems].min = 0.0;
174
+ elems[nelems].max = 0.0;
175
+ elems[nelems].step = 0.0;
176
+ nelems++;
177
+ }
178
+
179
+ #define portno(label) (is_voice_ctrl(label)?-1:nports++)
180
+
181
+ inline void VSTUI::add_elem(ui_elem_type_t type, const char *label, float *zone)
182
+ {
183
+ ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
184
+ if (elems1)
185
+ elems = elems1;
186
+ else
187
+ return;
188
+ elems[nelems].type = type;
189
+ elems[nelems].label = label;
190
+ elems[nelems].port = portno(label);
191
+ elems[nelems].zone = zone;
192
+ elems[nelems].ref = NULL;
193
+ elems[nelems].init = 0.0;
194
+ elems[nelems].min = 0.0;
195
+ elems[nelems].max = 1.0;
196
+ elems[nelems].step = 1.0;
197
+ nelems++;
198
+ }
199
+
200
+ inline void VSTUI::add_elem(ui_elem_type_t type, const char *label, float *zone, float init, float min, float max, float step)
201
+ {
202
+ ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
203
+ if (elems1)
204
+ elems = elems1;
205
+ else
206
+ return;
207
+ elems[nelems].type = type;
208
+ elems[nelems].label = label;
209
+ elems[nelems].port = portno(label);
210
+ elems[nelems].zone = zone;
211
+ elems[nelems].ref = NULL;
212
+ elems[nelems].init = init;
213
+ elems[nelems].min = min;
214
+ elems[nelems].max = max;
215
+ elems[nelems].step = step;
216
+ nelems++;
217
+ }
218
+
219
+ inline void VSTUI::add_elem(ui_elem_type_t type, const char *label, float *zone, float min, float max)
220
+ {
221
+ ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
222
+ if (elems1)
223
+ elems = elems1;
224
+ else
225
+ return;
226
+ elems[nelems].type = type;
227
+ elems[nelems].label = label;
228
+ elems[nelems].port = portno(label);
229
+ elems[nelems].zone = zone;
230
+ elems[nelems].ref = NULL;
231
+ elems[nelems].init = 0.0;
232
+ elems[nelems].min = min;
233
+ elems[nelems].max = max;
234
+ elems[nelems].step = 0.0;
235
+ nelems++;
236
+ }
237
+
238
+ inline bool VSTUI::is_voice_ctrl(const char *label)
239
+ {
240
+ if (!is_instr)
241
+ return false;
242
+ else if (!have_freq && !strcmp(label, "freq"))
243
+ return (have_freq = true);
244
+ else if (!have_gain && !strcmp(label, "gain"))
245
+ return (have_gain = true);
246
+ else if (!have_gate && !strcmp(label, "gate"))
247
+ return (have_gate = true);
248
+ else
249
+ return false;
250
+ }
251
+
252
+ void VSTUI::addButton(const char* label, float* zone)
253
+ { add_elem(UI_BUTTON, label, zone); }
254
+ void VSTUI::addCheckButton(const char* label, float* zone)
255
+ { add_elem(UI_CHECK_BUTTON, label, zone); }
256
+ void VSTUI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
257
+ { add_elem(UI_V_SLIDER, label, zone, init, min, max, step); }
258
+ void VSTUI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
259
+ { add_elem(UI_H_SLIDER, label, zone, init, min, max, step); }
260
+ void VSTUI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
261
+ { add_elem(UI_NUM_ENTRY, label, zone, init, min, max, step); }
262
+
263
+ void VSTUI::addHorizontalBargraph(const char* label, float* zone, float min, float max)
264
+ { add_elem(UI_H_BARGRAPH, label, zone, min, max); }
265
+ void VSTUI::addVerticalBargraph(const char* label, float* zone, float min, float max)
266
+ { add_elem(UI_V_BARGRAPH, label, zone, min, max); }
267
+
268
+ void VSTUI::openTabBox(const char* label)
269
+ { add_elem(UI_T_GROUP, label); }
270
+ void VSTUI::openHorizontalBox(const char* label)
271
+ { add_elem(UI_H_GROUP, label); }
272
+ void VSTUI::openVerticalBox(const char* label)
273
+ { add_elem(UI_V_GROUP, label); }
274
+ void VSTUI::closeBox()
275
+ { add_elem(UI_END_GROUP); }
276
+
277
+ void VSTUI::run() {}
278
+
279
+ //----------------------------------------------------------------------------
280
+ // FAUST generated signal processor
281
+ //----------------------------------------------------------------------------
282
+
283
+ <<includeclass>>
284
+
285
+ //----------------------------------------------------------------------------
286
+ // VST interface
287
+ //----------------------------------------------------------------------------
288
+
289
+ #line 286 "faustvst.cpp"
290
+
291
+ #include <assert.h>
292
+ #include <stdio.h>
293
+ #include <stdlib.h>
294
+
295
+ #include <boost/circular_buffer.hpp>
296
+
297
+ // Some boilerplate code pilfered from the mda Linux vst source code.
298
+ #include "pluginterfaces/vst2.x/aeffectx.h"
299
+ extern "C" {
300
+ #define VST_EXPORT __attribute__ ((visibility ("default")))
301
+ extern VST_EXPORT AEffect * VSTPluginMain(audioMasterCallback audioMaster);
302
+ // This is for legacy (<2.4) VST hosts which look for the 'main' entry point.
303
+ AEffect *main_plugin (audioMasterCallback audioMaster) asm ("main");
304
+ #define main main_plugin
305
+ VST_EXPORT AEffect * main(audioMasterCallback audioMaster)
306
+ {
307
+ return VSTPluginMain(audioMaster);
308
+ }
309
+ }
310
+
311
+ /* Setting NVOICES at compile time overrides meta data in the Faust source. If
312
+ set, this must be an integer value >= 0. A nonzero value indicates an
313
+ instrument (VSTi) plugin with the given maximum number of voices. Use 1 for
314
+ a monophonic synthesizer, and 0 for a simple effect plugin. If NVOICES
315
+ isn't defined at compile time then the number of voices of an instrument
316
+ plugin can also be set with the global "nvoices" meta data key in the Faust
317
+ source. This setting also adds a special "polyphony" control to the plugin
318
+ which can be used to dynamically adjust the actual number of voices in the
319
+ range 1..NVOICES. */
320
+ //#define NVOICES 16
321
+
322
+ /* This enables special polyphony/tuning controls on the GUI (VSTi only). */
323
+ #ifndef VOICE_CTRLS
324
+ #define VOICE_CTRLS 1
325
+ #endif
326
+
327
+ /* This enables a special "tuning" control in a VSTi plugin which lets you
328
+ select the MTS tuning to be used for the synth. In order to use this, you
329
+ just drop some sysex (.syx) files with MTS octave-based tunings in 1- or
330
+ 2-byte format into the ~/.fautvst/tuning directory (these can be generated
331
+ with the author's sclsyx program, https://bitbucket.org/agraef/sclsyx).
332
+ The control will only be shown if any .syx files were found at startup. 0
333
+ selects the default tuning (standard 12-tone equal temperament), i>0 the
334
+ tuning in the ith sysex file (in alphabetic order). */
335
+ #ifndef FAUST_MTS
336
+ #define FAUST_MTS 1
337
+ #endif
338
+
339
+ /* This allows various manifest data to be generated from the corresponding
340
+ metadata (author, name, description, license) in the Faust source. */
341
+ #ifndef FAUST_META
342
+ #define FAUST_META 1
343
+ #endif
344
+
345
+ /* This enables automatic MIDI controller mapping based on the midi:ctrl
346
+ attributes in the Faust source. We have this enabled by default, but you
347
+ may have to disable it if the custom controller mapping gets in the way of
348
+ the automation facilities that the host provides. (But then again if the
349
+ host wants to do its own controller mapping then it probably won't, or at
350
+ least shouldn't, send us the MIDI controllers in the first place.) */
351
+ #ifndef FAUST_MIDICC
352
+ #define FAUST_MIDICC 1
353
+ #endif
354
+
355
+ /* This enables or disables the plugin's custom Qt GUI (see the Qt-specific
356
+ part at the end of this module). This is disabled by default, but enabled
357
+ with gui=1 in the Makefile or the -gui option of the faust2vst script. */
358
+ #ifndef FAUST_UI
359
+ #define FAUST_UI 0
360
+ #endif
361
+
362
+ // You can define these for various debugging output items.
363
+ //#define DEBUG_META 1 // recognized MIDI controller metadata
364
+ //#define DEBUG_VOICES 1 // triggering of synth voices
365
+ //#define DEBUG_VOICE_ALLOC 1 // voice allocation
366
+ //#define DEBUG_MIDI 1 // incoming MIDI messages
367
+ //#define DEBUG_NOTES 1 // note messages
368
+ //#define DEBUG_MIDICC 1 // controller messages
369
+ //#define DEBUG_RPN 1 // RPN messages (pitch bend range, master tuning)
370
+ //#define DEBUG_MTS 1 // MTS messages (octave/scale tuning)
371
+
372
+ // Note and voice data structures.
373
+
374
+ struct NoteInfo {
375
+ uint8_t ch;
376
+ int8_t note;
377
+ };
378
+
379
+ struct VoiceData {
380
+ // Octave tunings (offsets in semitones) per MIDI channel.
381
+ float tuning[16][12];
382
+ // Allocated voices per MIDI channel and note.
383
+ int8_t notes[16][128];
384
+ // Free and used voices.
385
+ int n_free, n_used;
386
+ boost::circular_buffer<int> free_voices;
387
+ boost::circular_buffer<int> used_voices;
388
+ NoteInfo *note_info;
389
+ // Voices queued for note-offs (zero-length notes).
390
+ set<int> queued;
391
+ // Last gate value during run() for each voice. We need to keep track of
392
+ // these so that we can force the Faust synth to retrigger a note when
393
+ // needed.
394
+ float *lastgate;
395
+ // Current pitch bend and pitch bend range on each MIDI channel, in semitones.
396
+ float bend[16], range[16];
397
+ // Current coarse, fine and total master tuning on each MIDI channel (tuning
398
+ // offset relative to A4 = 440 Hz, in semitones).
399
+ float coarse[16], fine[16], tune[16];
400
+ VoiceData(int n) : free_voices(n), used_voices(n) { }
401
+ };
402
+
403
+ #if FAUST_MTS
404
+
405
+ // Helper classes to read and store MTS tunings.
406
+
407
+ #include <sys/types.h>
408
+ #include <sys/stat.h>
409
+ #include <dirent.h>
410
+
411
+ #include <string>
412
+ #include <vector>
413
+
414
+ struct MTSTuning {
415
+ char *name; // name of the tuning
416
+ int len; // length of sysex data in bytes
417
+ unsigned char *data; // sysex data
418
+ MTSTuning() : name(0), len(0), data(0) {}
419
+ MTSTuning& operator=(const MTSTuning &t)
420
+ {
421
+ if (this == &t) return *this;
422
+ if (name) free(name); if (data) free(data);
423
+ name = 0; data = 0; len = t.len;
424
+ if (t.name) {
425
+ name = strdup(t.name); assert(name);
426
+ }
427
+ if (t.data) {
428
+ data = (unsigned char*)malloc(len); assert(data);
429
+ memcpy(data, t.data, len);
430
+ }
431
+ return *this;
432
+ }
433
+ MTSTuning(const MTSTuning& t) : name(0), len(0), data(0)
434
+ { *this = t; }
435
+ MTSTuning(const char *filename);
436
+ ~MTSTuning()
437
+ { if (name) free(name); if (data) free(data); }
438
+ };
439
+
440
+ MTSTuning::MTSTuning(const char *filename)
441
+ {
442
+ FILE *fp = fopen(filename, "rb");
443
+ name = 0; len = 0; data = 0;
444
+ if (!fp) return;
445
+ struct stat st;
446
+ if (fstat(fileno(fp), &st)) return;
447
+ len = st.st_size;
448
+ data = (unsigned char*)calloc(len, 1);
449
+ if (!data) {
450
+ len = 0; fclose(fp);
451
+ return;
452
+ }
453
+ assert(len > 0);
454
+ if (fread(data, 1, len, fp) < len) {
455
+ free(data); len = 0; data = 0; fclose(fp);
456
+ return;
457
+ }
458
+ fclose(fp);
459
+ // Do some basic sanity checks.
460
+ if (data[0] != 0xf0 || data[len-1] != 0xf7 || // not a sysex message
461
+ (data[1] != 0x7e && data[1] != 0x7f) || data[3] != 8 || // not MTS
462
+ !((len == 21 && data[4] == 8) ||
463
+ (len == 33 && data[4] == 9))) { // no 1- or 2-byte tuning
464
+ free(data); len = 0; data = 0;
465
+ return;
466
+ }
467
+ // Name of the tuning is the basename of the file, without the trailing .syx
468
+ // suffix.
469
+ string nm = filename;
470
+ size_t p = nm.rfind(".syx");
471
+ if (p != string::npos) nm.erase(p);
472
+ p = nm.rfind('/');
473
+ if (p != string::npos) nm.erase(0, p+1);
474
+ name = strdup(nm.c_str());
475
+ assert(name);
476
+ }
477
+
478
+ struct MTSTunings {
479
+ vector<MTSTuning> tuning;
480
+ MTSTunings() {}
481
+ MTSTunings(const char *path);
482
+ };
483
+
484
+ static bool compareByName(const MTSTuning &a, const MTSTuning &b)
485
+ {
486
+ return strcmp(a.name, b.name) < 0;
487
+ }
488
+
489
+ MTSTunings::MTSTunings(const char *path)
490
+ {
491
+ DIR *dp = opendir(path);
492
+ if (!dp) return;
493
+ struct dirent *d;
494
+ while ((d = readdir(dp))) {
495
+ string nm = d->d_name;
496
+ if (nm.length() > 4 && nm.substr(nm.length()-4) == ".syx") {
497
+ string pathname = path;
498
+ pathname += "/";
499
+ pathname += nm;
500
+ MTSTuning t(pathname.c_str());
501
+ if (t.data) tuning.push_back(t);
502
+ }
503
+ }
504
+ closedir(dp);
505
+ // sort found tunings by name
506
+ sort(tuning.begin(), tuning.end(), compareByName);
507
+ }
508
+
509
+ #endif
510
+
511
+ #if FAUST_MIDICC
512
+ static float ctrlval(const ui_elem_t &el, uint8_t v)
513
+ {
514
+ // Translate the given MIDI controller value to the range and stepsize
515
+ // indicated by the Faust control.
516
+ switch (el.type) {
517
+ case UI_BUTTON: case UI_CHECK_BUTTON:
518
+ return (float)(v>=64);
519
+ default:
520
+ /* Continuous controllers. The problem here is that the range 0..127 is
521
+ not symmetric. We'd like to map 64 to the center of the range
522
+ (max-min)/2 and at the same time retain the full control range
523
+ min..max. So let's just pretend that there are 128 controller values
524
+ and map value 127 to the max value anyway. */
525
+ if (v==127)
526
+ return el.max;
527
+ else
528
+ // XXXFIXME: We might want to add proper quantization according to
529
+ // el.step here.
530
+ return el.min+(el.max-el.min)*v/128;
531
+ }
532
+ }
533
+ #endif
534
+
535
+ /***************************************************************************/
536
+
537
+ /* Polyphonic Faust plugin data structure. XXXTODO: At present this is just a
538
+ big struct which exposes all requisite data. Some more work is needed to
539
+ make the interface a bit more abstract and properly encapsulate the
540
+ internal data structures, so that implementation details can be changed
541
+ more easily. */
542
+
543
+ struct VSTPlugin {
544
+ const int maxvoices; // maximum number of voices (zero if not an instrument)
545
+ const int ndsps; // number of dsp instances (1 if maxvoices==0)
546
+ int nvoices; // current number of voices (<= maxvoices)
547
+ bool active; // activation status
548
+ bool modified; // keep track of modified controls
549
+ int rate; // sampling rate
550
+ mydsp **dsp; // the dsps
551
+ VSTUI **ui; // their Faust interface descriptions
552
+ int n_in, n_out; // number of input and output control ports
553
+ int poly, tuning; // polyphony and tuning ports
554
+ int *ctrls; // Faust ui elements (indices into ui->elems)
555
+ float *ports; // port data (plugin-side control values)
556
+ float *portvals; // cached port data from the last run
557
+ float *midivals[16]; // per-channel midi data
558
+ int *inctrls, *outctrls; // indices for active and passive controls
559
+ int freq, gain, gate; // indices of voice controls
560
+ const char **units; // unit names (control meta data)
561
+ unsigned n_samples; // current block size
562
+ float **outbuf; // audio buffers for mixing down the voices
563
+ float **inbuf; // dummy input buffer used for retriggering notes
564
+ std::map<uint8_t,int> ctrlmap; // MIDI controller map (control meta data)
565
+ // Current RPN MSB and LSB numbers, as set with controllers 101 and 100.
566
+ uint8_t rpn_msb[16], rpn_lsb[16];
567
+ // Current data entry MSB and LSB numbers, as set with controllers 6 and 38.
568
+ uint8_t data_msb[16], data_lsb[16];
569
+ // Synth voice data (instruments only).
570
+ VoiceData *vd;
571
+
572
+ // Static methods. These all use static data so they can be invoked before
573
+ // instantiating a plugin.
574
+
575
+ // Global meta data (dsp name, author, etc.).
576
+ static MyMeta *meta;
577
+ static void init_meta()
578
+ {
579
+ if (!meta && (meta = new MyMeta)) {
580
+ // We allocate the temporary dsp object on the heap here, to prevent
581
+ // large dsp objects from running out of stack in environments where
582
+ // stack space is precious (e.g., Reaper). Note that if any of these
583
+ // allocations fail then no meta data will be available, but at least we
584
+ // won't make the host crash and burn.
585
+ mydsp* tmp_dsp = new mydsp();
586
+ if (tmp_dsp) {
587
+ tmp_dsp->metadata(meta);
588
+ delete tmp_dsp;
589
+ }
590
+ }
591
+ }
592
+ static const char *meta_get(const char *key, const char *deflt)
593
+ {
594
+ init_meta();
595
+ return meta?meta->get(key, deflt):deflt;
596
+ }
597
+
598
+ static const char *pluginName()
599
+ {
600
+ return meta_get("name", "mydsp");
601
+ }
602
+
603
+ static const char *pluginAuthor()
604
+ {
605
+ return meta_get("author", "");
606
+ }
607
+
608
+ static const char *pluginDescription()
609
+ {
610
+ return meta_get("description", "");
611
+ }
612
+
613
+ static const char *pluginVersion()
614
+ {
615
+ return meta_get("version", "0.0");
616
+ }
617
+
618
+ // Load a collection of sysex files with MTS tunings in ~/.faust/tuning.
619
+ static int n_tunings;
620
+ #if FAUST_MTS
621
+ static MTSTunings *mts;
622
+
623
+ static MTSTunings *load_sysex_data()
624
+ {
625
+ if (!mts) {
626
+ string mts_path;
627
+ // Look for FAUST_HOME. If that isn't set, try $HOME/.faust. If HOME
628
+ // isn't set either, just assume a .faust subdir of the cwd.
629
+ const char *home = getenv("FAUST_HOME");
630
+ if (home)
631
+ mts_path = home;
632
+ else {
633
+ home = getenv("HOME");
634
+ if (home) {
635
+ mts_path = home;
636
+ mts_path += "/.faust";
637
+ } else
638
+ mts_path = ".faust";
639
+ }
640
+ // MTS tunings are looked for in this subdir.
641
+ mts_path += "/tuning";
642
+ mts = new MTSTunings(mts_path.c_str());
643
+ #ifdef __APPLE__
644
+ if (!mts || mts->tuning.size() == 0) {
645
+ // Also check ~/Library/Faust/Tuning on the Mac.
646
+ home = getenv("HOME");
647
+ if (home) {
648
+ if (mts) delete mts;
649
+ mts_path = home;
650
+ mts_path += "/Library/Faust/Tuning";
651
+ mts = new MTSTunings(mts_path.c_str());
652
+ }
653
+ }
654
+ #endif
655
+ n_tunings = mts->tuning.size();
656
+ }
657
+ return mts;
658
+ }
659
+ #endif
660
+
661
+ // The number of voices of an instrument plugin. We get this information
662
+ // from the global meta data (nvoices key) of the dsp module if present, and
663
+ // you can also override this setting at compile time by defining the
664
+ // NVOICES macro. If neither is defined or the value is zero then the plugin
665
+ // becomes a simple audio effect instead.
666
+ static int numVoices()
667
+ {
668
+ bool midi_sync = false;
669
+ int nvoices = 0;
670
+ mydsp* tmp_dsp = new mydsp();
671
+ MidiMeta::analyse(tmp_dsp, midi_sync, nvoices);
672
+ delete tmp_dsp;
673
+ return nvoices;
674
+ }
675
+
676
+ // The number of controls of the dsp. Some plugin interfaces need that
677
+ // information beforehand, so we create a dummy instance of the UI data to
678
+ // retrieve it. For instrument plugins, we also reserve extra ports for the
679
+ // polyphony and tuning controls, if applicable.
680
+ static int numControls()
681
+ {
682
+ const int num_voices = numVoices();
683
+ // Allocate temporary dsp object on the heap (see comments under init_meta
684
+ // for explanation).
685
+ mydsp *dsp = new mydsp();
686
+ if (!dsp) return 0;
687
+ VSTUI ui(num_voices);
688
+ dsp->buildUserInterface(&ui);
689
+ delete dsp;
690
+ // reserve one extra port for the polyphony control (instruments only)
691
+ int num_extra = (num_voices>0);
692
+ #if FAUST_MTS
693
+ // likewise for the tuning control
694
+ if (num_voices>0 && load_sysex_data())
695
+ num_extra += (mts->tuning.size()>0);
696
+ #endif
697
+ return ui.nports+num_extra;
698
+ }
699
+
700
+ // Instance methods.
701
+
702
+ VSTPlugin(const int num_voices, const int sr)
703
+ : maxvoices(num_voices), ndsps(num_voices<=0?1:num_voices),
704
+ vd(num_voices>0?new VoiceData(num_voices):0)
705
+ {
706
+ // Initialize static data.
707
+ init_meta();
708
+ #if FAUST_MTS
709
+ // Synth: load tuning sysex data if present.
710
+ if (num_voices>0) load_sysex_data();
711
+ #endif
712
+ // Allocate data structures and set some reasonable defaults.
713
+ dsp = (mydsp**)calloc(ndsps, sizeof(mydsp*));
714
+ ui = (VSTUI**)calloc(ndsps, sizeof(VSTUI*));
715
+ assert(dsp && ui);
716
+ if (vd) {
717
+ vd->note_info = (NoteInfo*)calloc(ndsps, sizeof(NoteInfo));
718
+ vd->lastgate = (float*)calloc(ndsps, sizeof(float));
719
+ assert(vd->note_info && vd->lastgate);
720
+ }
721
+ active = modified = false;
722
+ rate = sr;
723
+ nvoices = maxvoices;
724
+ n_in = n_out = 0;
725
+ poly = maxvoices/2;
726
+ tuning = 0;
727
+ freq = gain = gate = -1;
728
+ for (int i = 0; i < 16; i++) {
729
+ rpn_msb[i] = rpn_lsb[i] = 0x7f;
730
+ data_msb[i] = data_lsb[i] = 0;
731
+ }
732
+ if (vd) {
733
+ vd->n_free = maxvoices;
734
+ for (int i = 0; i < maxvoices; i++) {
735
+ vd->free_voices.push_back(i);
736
+ vd->lastgate[i] = 0.0f;
737
+ }
738
+ for (int i = 0; i < 16; i++) {
739
+ vd->bend[i] = 0.0f;
740
+ vd->range[i] = 2.0f;
741
+ vd->coarse[i] = vd->fine[i] = vd->tune[i] = 0.0f;
742
+ for (int j = 0; j < 12; j++)
743
+ vd->tuning[i][j] = 0.0f;
744
+ }
745
+ vd->n_used = 0;
746
+ memset(vd->notes, 0xff, sizeof(vd->notes));
747
+ }
748
+ n_samples = 0;
749
+ ctrls = inctrls = outctrls = NULL;
750
+ inbuf = outbuf = NULL;
751
+ ports = portvals = NULL;
752
+ units = NULL;
753
+ memset(midivals, 0, sizeof(midivals));
754
+ // Initialize the Faust DSPs.
755
+ for (int i = 0; i < ndsps; i++) {
756
+ dsp[i] = new mydsp();
757
+ ui[i] = new VSTUI(num_voices);
758
+ dsp[i]->init(rate);
759
+ dsp[i]->buildUserInterface(ui[i]);
760
+ }
761
+ // The ports are numbered as follows: 0..k-1 are the control ports, then
762
+ // come the n audio input ports, then the m audio output ports, and
763
+ // finally the midi input port and the polyphony and tuning controls. This
764
+ // mimics the port layout of faust-lv2, but should work fine with other
765
+ // kinds of plugin architectures as well.
766
+ int k = ui[0]->nports, p = 0, q = 0;
767
+ int n = dsp[0]->getNumInputs(), m = dsp[0]->getNumOutputs();
768
+ // Allocate tables for the built-in control elements and their ports.
769
+ ctrls = (int*)calloc(k, sizeof(int));
770
+ inctrls = (int*)calloc(k, sizeof(int));
771
+ outctrls = (int*)calloc(k, sizeof(int));
772
+ ports = (float*)calloc(k, sizeof(float));
773
+ portvals = (float*)calloc(k, sizeof(float));
774
+ units = (const char**)calloc(k, sizeof(const char*));
775
+ assert(k == 0 || (ctrls && inctrls && outctrls &&
776
+ ports && portvals && units));
777
+ for (int ch = 0; ch < 16; ch++) {
778
+ midivals[ch] = (float*)calloc(k, sizeof(float));
779
+ assert(k == 0 || midivals[ch]);
780
+ }
781
+ // Scan the Faust UI for active and passive controls which become the
782
+ // input and output control ports of the plugin, respectively.
783
+ for (int i = 0, j = 0; i < ui[0]->nelems; i++) {
784
+ const char *unit = NULL;
785
+ switch (ui[0]->elems[i].type) {
786
+ case UI_T_GROUP: case UI_H_GROUP: case UI_V_GROUP: case UI_END_GROUP:
787
+ // control groups (ignored right now)
788
+ break;
789
+ case UI_H_BARGRAPH: case UI_V_BARGRAPH:
790
+ // passive controls (output ports)
791
+ ctrls[j++] = i;
792
+ outctrls[q++] = i;
793
+ {
794
+ std::map< int, list<strpair> >::iterator it =
795
+ ui[0]->metadata.find(i);
796
+ if (it != ui[0]->metadata.end()) {
797
+ for (std::list<strpair>::iterator jt = it->second.begin();
798
+ jt != it->second.end(); jt++) {
799
+ const char *key = jt->first, *val = jt->second;
800
+ #if DEBUG_META
801
+ fprintf(stderr, "ctrl '%s' meta: '%s' -> '%s'\n",
802
+ ui[0]->elems[i].label, key, val);
803
+ #endif
804
+ if (strcmp(key, "unit") == 0)
805
+ unit = val;
806
+ }
807
+ }
808
+ int p = ui[0]->elems[i].port;
809
+ units[p] = unit;
810
+ }
811
+ break;
812
+ default:
813
+ // active controls (input ports)
814
+ if (maxvoices == 0)
815
+ goto noinstr;
816
+ else if (freq == -1 &&
817
+ !strcmp(ui[0]->elems[i].label, "freq"))
818
+ freq = i;
819
+ else if (gain == -1 &&
820
+ !strcmp(ui[0]->elems[i].label, "gain"))
821
+ gain = i;
822
+ else if (gate == -1 &&
823
+ !strcmp(ui[0]->elems[i].label, "gate"))
824
+ gate = i;
825
+ else {
826
+ noinstr:
827
+ std::map< int, list<strpair> >::iterator it =
828
+ ui[0]->metadata.find(i);
829
+ if (it != ui[0]->metadata.end()) {
830
+ // Scan for controller mappings and other control meta data.
831
+ for (std::list<strpair>::iterator jt = it->second.begin();
832
+ jt != it->second.end(); jt++) {
833
+ const char *key = jt->first, *val = jt->second;
834
+ #if DEBUG_META
835
+ fprintf(stderr, "ctrl '%s' meta: '%s' -> '%s'\n",
836
+ ui[0]->elems[i].label, key, val);
837
+ #endif
838
+ if (strcmp(key, "unit") == 0) {
839
+ unit = val;
840
+ #if FAUST_MIDICC
841
+ } else if (strcmp(key, "midi") == 0) {
842
+ unsigned num;
843
+ if (sscanf(val, "ctrl %u", &num) < 1) continue;
844
+ #if 0 // enable this to get feedback about controller assignments
845
+ const char *dsp_name = pluginName();
846
+ fprintf(stderr, "%s: cc %d -> %s\n", dsp_name, num,
847
+ ui[0]->elems[i].label);
848
+ #endif
849
+ ctrlmap.insert(std::pair<uint8_t,int>(num, p));
850
+ #endif
851
+ }
852
+ }
853
+ }
854
+ ctrls[j++] = i;
855
+ inctrls[p++] = i;
856
+ int p = ui[0]->elems[i].port;
857
+ float val = ui[0]->elems[i].init;
858
+ assert(p>=0);
859
+ portvals[p] = ports[p] = val;
860
+ units[p] = unit;
861
+ for (int ch = 0; ch < 16; ch++)
862
+ midivals[ch][p] = val;
863
+ }
864
+ break;
865
+ }
866
+ }
867
+ // Realloc the inctrls and outctrls vectors to their appropriate sizes.
868
+ inctrls = (int*)realloc(inctrls, p*sizeof(int));
869
+ assert(p == 0 || inctrls);
870
+ outctrls = (int*)realloc(outctrls, q*sizeof(int));
871
+ assert(q == 0 || outctrls);
872
+ n_in = p; n_out = q;
873
+ if (maxvoices > 0) {
874
+ // Initialize the mixdown buffer.
875
+ outbuf = (float**)calloc(m, sizeof(float*));
876
+ assert(m == 0 || outbuf);
877
+ // We start out with a blocksize of 512 samples here. Hopefully this is
878
+ // enough for most realtime hosts so that we can avoid reallocations
879
+ // later when we know what the actual blocksize is.
880
+ n_samples = 512;
881
+ for (int i = 0; i < m; i++) {
882
+ outbuf[i] = (float*)malloc(n_samples*sizeof(float));
883
+ assert(outbuf[i]);
884
+ }
885
+ // Initialize a 1-sample dummy input buffer used for retriggering notes.
886
+ inbuf = (float**)calloc(n, sizeof(float*));
887
+ assert(n == 0 || inbuf);
888
+ for (int i = 0; i < m; i++) {
889
+ inbuf[i] = (float*)malloc(sizeof(float));
890
+ assert(inbuf[i]);
891
+ *inbuf[i] = 0.0f;
892
+ }
893
+ }
894
+ }
895
+
896
+ ~VSTPlugin()
897
+ {
898
+ const int n = dsp[0]->getNumInputs();
899
+ const int m = dsp[0]->getNumOutputs();
900
+ for (int i = 0; i < ndsps; i++) {
901
+ delete dsp[i];
902
+ delete ui[i];
903
+ }
904
+ free(ctrls);
905
+ free(inctrls);
906
+ free(outctrls);
907
+ free(ports);
908
+ free(portvals);
909
+ free(units);
910
+ for (int ch = 0; ch < 16; ch++)
911
+ free(midivals[ch]);
912
+ if (inbuf) {
913
+ for (int i = 0; i < n; i++)
914
+ free(inbuf[i]);
915
+ free(inbuf);
916
+ }
917
+ if (outbuf) {
918
+ for (int i = 0; i < m; i++)
919
+ free(outbuf[i]);
920
+ free(outbuf);
921
+ }
922
+ free(dsp);
923
+ free(ui);
924
+ if (vd) {
925
+ free(vd->note_info);
926
+ free(vd->lastgate);
927
+ delete vd;
928
+ }
929
+ }
930
+
931
+ // Voice allocation.
932
+
933
+ #if DEBUG_VOICE_ALLOC
934
+ void print_voices(const char *msg)
935
+ {
936
+ fprintf(stderr, "%s: notes =", msg);
937
+ for (uint8_t ch = 0; ch < 16; ch++)
938
+ for (int note = 0; note < 128; note++)
939
+ if (vd->notes[ch][note] >= 0)
940
+ fprintf(stderr, " [%d] %d(#%d)", ch, note, vd->notes[ch][note]);
941
+ fprintf(stderr, "\nqueued (%d):", vd->queued.size());
942
+ for (int i = 0; i < nvoices; i++)
943
+ if (vd->queued.find(i) != vd->queued.end()) fprintf(stderr, " #%d", i);
944
+ fprintf(stderr, "\nused (%d):", vd->n_used);
945
+ for (boost::circular_buffer<int>::iterator it = vd->used_voices.begin();
946
+ it != vd->used_voices.end(); it++)
947
+ fprintf(stderr, " #%d->%d", *it, vd->note_info[*it].note);
948
+ fprintf(stderr, "\nfree (%d):", vd->n_free);
949
+ for (boost::circular_buffer<int>::iterator it = vd->free_voices.begin();
950
+ it != vd->free_voices.end(); it++)
951
+ fprintf(stderr, " #%d", *it);
952
+ fprintf(stderr, "\n");
953
+ }
954
+ #endif
955
+
956
+ int alloc_voice(uint8_t ch, int8_t note, int8_t vel)
957
+ {
958
+ int i = vd->notes[ch][note];
959
+ if (i >= 0) {
960
+ // note already playing on same channel, retrigger it
961
+ voice_off(i);
962
+ voice_on(i, note, vel, ch);
963
+ // move this voice to the end of the used list
964
+ for (boost::circular_buffer<int>::iterator it =
965
+ vd->used_voices.begin();
966
+ it != vd->used_voices.end(); it++) {
967
+ if (*it == i) {
968
+ vd->used_voices.erase(it);
969
+ vd->used_voices.push_back(i);
970
+ break;
971
+ }
972
+ }
973
+ #if DEBUG_VOICE_ALLOC
974
+ print_voices("retrigger");
975
+ #endif
976
+ return i;
977
+ } else if (vd->n_free > 0) {
978
+ // take voice from free list
979
+ int i = vd->free_voices.front();
980
+ vd->free_voices.pop_front();
981
+ vd->n_free--;
982
+ vd->used_voices.push_back(i);
983
+ vd->note_info[i].ch = ch;
984
+ vd->note_info[i].note = note;
985
+ vd->n_used++;
986
+ voice_on(i, note, vel, ch);
987
+ vd->notes[ch][note] = i;
988
+ #if DEBUG_VOICE_ALLOC
989
+ print_voices("alloc");
990
+ #endif
991
+ return i;
992
+ } else {
993
+ // steal a voice
994
+ assert(vd->n_used > 0);
995
+ // FIXME: Maybe we should look for the oldest note on the *current*
996
+ // channel here, but this is faster.
997
+ int i = vd->used_voices.front();
998
+ int oldch = vd->note_info[i].ch;
999
+ int oldnote = vd->note_info[i].note;
1000
+ voice_off(i);
1001
+ vd->notes[oldch][oldnote] = -1;
1002
+ vd->queued.erase(i);
1003
+ vd->used_voices.pop_front();
1004
+ vd->used_voices.push_back(i);
1005
+ vd->note_info[i].ch = ch;
1006
+ vd->note_info[i].note = note;
1007
+ voice_on(i, note, vel, ch);
1008
+ vd->notes[ch][note] = i;
1009
+ #if DEBUG_VOICE_ALLOC
1010
+ print_voices("steal");
1011
+ #endif
1012
+ return i;
1013
+ }
1014
+ }
1015
+
1016
+ int dealloc_voice(uint8_t ch, int8_t note, int8_t vel)
1017
+ {
1018
+ int i = vd->notes[ch][note];
1019
+ if (i >= 0) {
1020
+ if (vd->lastgate[i] == 0.0f && gate >= 0) {
1021
+ // zero-length note, queued for later
1022
+ vd->queued.insert(i);
1023
+ vd->notes[ch][note] = -1;
1024
+ #if DEBUG_VOICE_ALLOC
1025
+ print_voices("dealloc (queued)");
1026
+ #endif
1027
+ return i;
1028
+ }
1029
+ assert(vd->n_free < nvoices);
1030
+ vd->free_voices.push_back(i);
1031
+ vd->n_free++;
1032
+ voice_off(i);
1033
+ vd->notes[ch][note] = -1;
1034
+ // erase this voice from the used list
1035
+ for (boost::circular_buffer<int>::iterator it =
1036
+ vd->used_voices.begin();
1037
+ it != vd->used_voices.end(); it++) {
1038
+ if (*it == i) {
1039
+ vd->used_voices.erase(it);
1040
+ vd->n_used--;
1041
+ break;
1042
+ }
1043
+ }
1044
+ #if DEBUG_VOICE_ALLOC
1045
+ print_voices("dealloc");
1046
+ #endif
1047
+ return i;
1048
+ }
1049
+ return -1;
1050
+ }
1051
+
1052
+
1053
+ float midicps(int8_t note, uint8_t chan)
1054
+ {
1055
+ float pitch = note + vd->tune[chan] +
1056
+ vd->tuning[chan][note%12] + vd->bend[chan];
1057
+ return 440.0*pow(2, (pitch-69.0)/12.0);
1058
+ }
1059
+
1060
+ void voice_on(int i, int8_t note, int8_t vel, uint8_t ch)
1061
+ {
1062
+ if (vd->lastgate[i] == 1.0f && gate >= 0) {
1063
+ // Make sure that the synth sees the 0.0f gate so that the voice is
1064
+ // properly retriggered.
1065
+ *ui[i]->elems[gate].zone = 0.0f;
1066
+ dsp[i]->compute(1, inbuf, outbuf);
1067
+ }
1068
+ #if DEBUG_VOICES
1069
+ fprintf(stderr, "voice on: %d %d (%g Hz) %d (%g)\n", i,
1070
+ note, midicps(note, ch), vel, vel/127.0);
1071
+ #endif
1072
+ if (freq >= 0)
1073
+ *ui[i]->elems[freq].zone = midicps(note, ch);
1074
+ if (gate >= 0)
1075
+ *ui[i]->elems[gate].zone = 1.0f;
1076
+ if (gain >= 0)
1077
+ *ui[i]->elems[gain].zone = vel/127.0;
1078
+ // reinitialize the per-channel control data for this voice
1079
+ for (int idx = 0; idx < n_in; idx++) {
1080
+ int j = inctrls[idx], k = ui[0]->elems[j].port;
1081
+ *ui[i]->elems[j].zone = midivals[ch][k];
1082
+ }
1083
+ }
1084
+
1085
+ void voice_off(int i)
1086
+ {
1087
+ #if DEBUG_VOICES
1088
+ fprintf(stderr, "voice off: %d\n", i);
1089
+ #endif
1090
+ if (gate >= 0)
1091
+ *ui[i]->elems[gate].zone = 0.0f;
1092
+ }
1093
+
1094
+ void update_voices(uint8_t chan)
1095
+ {
1096
+ // update running voices on the given channel after tuning or pitch bend
1097
+ // changes
1098
+ for (boost::circular_buffer<int>::iterator it =
1099
+ vd->used_voices.begin();
1100
+ it != vd->used_voices.end(); it++) {
1101
+ int i = *it;
1102
+ if (vd->note_info[i].ch == chan && freq >= 0) {
1103
+ int note = vd->note_info[i].note;
1104
+ *ui[i]->elems[freq].zone = midicps(note, chan);
1105
+ }
1106
+ }
1107
+ }
1108
+
1109
+ void all_notes_off()
1110
+ {
1111
+ for (int i = 0; i < nvoices; i++)
1112
+ voice_off(i);
1113
+ for (int i = 0; i < 16; i++)
1114
+ vd->bend[i] = 0.0f;
1115
+ memset(vd->notes, 0xff, sizeof(vd->notes));
1116
+ vd->free_voices.clear();
1117
+ vd->n_free = nvoices;
1118
+ for (int i = 0; i < nvoices; i++)
1119
+ vd->free_voices.push_back(i);
1120
+ vd->queued.clear();
1121
+ vd->used_voices.clear();
1122
+ vd->n_used = 0;
1123
+ }
1124
+
1125
+ void all_notes_off(uint8_t chan)
1126
+ {
1127
+ for (boost::circular_buffer<int>::iterator it =
1128
+ vd->used_voices.begin();
1129
+ it != vd->used_voices.end(); ) {
1130
+ int i = *it;
1131
+ if (vd->note_info[i].ch == chan) {
1132
+ assert(vd->n_free < nvoices);
1133
+ vd->free_voices.push_back(i);
1134
+ vd->n_free++;
1135
+ voice_off(i);
1136
+ vd->notes[vd->note_info[i].ch][vd->note_info[i].note] = -1;
1137
+ vd->queued.erase(i);
1138
+ // erase this voice from the used list
1139
+ it = vd->used_voices.erase(it);
1140
+ vd->n_used--;
1141
+ #if DEBUG_VOICE_ALLOC
1142
+ print_voices("dealloc (all-notes-off)");
1143
+ #endif
1144
+ } else
1145
+ it++;
1146
+ }
1147
+ vd->bend[chan] = 0.0f;
1148
+ }
1149
+
1150
+ void queued_notes_off()
1151
+ {
1152
+ if (vd->queued.empty()) return;
1153
+ for (int i = 0; i < nvoices; i++)
1154
+ if (vd->queued.find(i) != vd->queued.end()) {
1155
+ assert(vd->n_free < nvoices);
1156
+ vd->free_voices.push_back(i);
1157
+ vd->n_free++;
1158
+ voice_off(i);
1159
+ vd->notes[vd->note_info[i].ch][vd->note_info[i].note] = -1;
1160
+ vd->queued.erase(i);
1161
+ // erase this voice from the used list
1162
+ for (boost::circular_buffer<int>::iterator it =
1163
+ vd->used_voices.begin();
1164
+ it != vd->used_voices.end(); it++) {
1165
+ if (*it == i) {
1166
+ vd->used_voices.erase(it);
1167
+ vd->n_used--;
1168
+ break;
1169
+ }
1170
+ }
1171
+ #if DEBUG_VOICE_ALLOC
1172
+ print_voices("dealloc (unqueued)");
1173
+ #endif
1174
+ }
1175
+ }
1176
+
1177
+ // Plugin activation status. suspend() deactivates a plugin (disables audio
1178
+ // processing), resume() reactivates it. Also, set_rate() changes the sample
1179
+ // rate. Note that the audio and MIDI process functions (see below) can
1180
+ // still be called in deactivated state, but this is optional. The plugin
1181
+ // tries to do some reasonable processing in either case, no matter whether
1182
+ // the host plugin architecture actually executes callbacks in suspended
1183
+ // state or not.
1184
+
1185
+ void suspend()
1186
+ {
1187
+ active = false;
1188
+ if (maxvoices > 0) all_notes_off();
1189
+ }
1190
+
1191
+ void resume()
1192
+ {
1193
+ for (int i = 0; i < ndsps; i++)
1194
+ dsp[i]->init(rate);
1195
+ for (int i = 0, j = 0; i < ui[0]->nelems; i++) {
1196
+ int p = ui[0]->elems[i].port;
1197
+ if (p >= 0) {
1198
+ float val = ui[0]->elems[i].init;
1199
+ portvals[p] = val;
1200
+ }
1201
+ }
1202
+ active = true;
1203
+ }
1204
+
1205
+ void set_rate(int sr)
1206
+ {
1207
+ rate = sr;
1208
+ for (int i = 0; i < ndsps; i++)
1209
+ dsp[i]->init(rate);
1210
+ }
1211
+
1212
+ // Audio and MIDI process functions. The plugin should run these in the
1213
+ // appropriate real-time callbacks.
1214
+
1215
+ void process_audio(int blocksz, float **inputs, float **outputs)
1216
+ {
1217
+ int n = dsp[0]->getNumInputs(), m = dsp[0]->getNumOutputs();
1218
+ AVOIDDENORMALS;
1219
+ modified = false;
1220
+ if (maxvoices > 0) queued_notes_off();
1221
+ if (!active) {
1222
+ // Depending on the plugin architecture, this code might never be
1223
+ // invoked, since the plugin is deactivitated at this point. But let's
1224
+ // do something reasonable here anyway.
1225
+ if (n == m) {
1226
+ // copy inputs to outputs
1227
+ for (int i = 0; i < m; i++)
1228
+ for (unsigned j = 0; j < blocksz; j++)
1229
+ outputs[i][j] = inputs[i][j];
1230
+ } else {
1231
+ // silence
1232
+ for (int i = 0; i < m; i++)
1233
+ for (unsigned j = 0; j < blocksz; j++)
1234
+ outputs[i][j] = 0.0f;
1235
+ }
1236
+ return;
1237
+ }
1238
+ // Handle changes in the polyphony control.
1239
+ if (nvoices != poly && poly > 0 && poly <= maxvoices) {
1240
+ modified = true;
1241
+ for (int i = 0; i < nvoices; i++)
1242
+ voice_off(i);
1243
+ nvoices = poly;
1244
+ // Reset the voice allocation.
1245
+ memset(vd->notes, 0xff, sizeof(vd->notes));
1246
+ vd->free_voices.clear();
1247
+ vd->n_free = nvoices;
1248
+ for (int i = 0; i < nvoices; i++)
1249
+ vd->free_voices.push_back(i);
1250
+ vd->used_voices.clear();
1251
+ vd->n_used = 0;
1252
+ } else
1253
+ poly = nvoices;
1254
+ // Only update the controls (of all voices simultaneously) if a port value
1255
+ // actually changed. This is necessary to allow MIDI controllers to modify
1256
+ // the values for individual MIDI channels (see processEvents below). Also
1257
+ // note that this will be done *after* processing the MIDI controller data
1258
+ // for the current audio block, so manual inputs can still override these.
1259
+ bool is_instr = maxvoices > 0;
1260
+ for (int i = 0; i < n_in; i++) {
1261
+ int j = inctrls[i], k = ui[0]->elems[j].port;
1262
+ float &oldval = portvals[k], newval = ports[k];
1263
+ if (newval != oldval) {
1264
+ modified = true;
1265
+ if (is_instr) {
1266
+ // instrument: update running voices
1267
+ for (boost::circular_buffer<int>::iterator it =
1268
+ vd->used_voices.begin();
1269
+ it != vd->used_voices.end(); it++) {
1270
+ int i = *it;
1271
+ *ui[i]->elems[j].zone = newval;
1272
+ }
1273
+ } else {
1274
+ // simple effect: here we only have a single dsp instance
1275
+ *ui[0]->elems[j].zone = newval;
1276
+ }
1277
+ // also update the MIDI controller data for all channels (manual
1278
+ // control input is always omni)
1279
+ for (int ch = 0; ch < 16; ch++)
1280
+ midivals[ch][k] = newval;
1281
+ // record the new value
1282
+ oldval = newval;
1283
+ }
1284
+ }
1285
+ // Initialize the output buffers.
1286
+ if (n_samples < blocksz) {
1287
+ // We need to enlarge the buffers. We're not officially allowed to do
1288
+ // this here (presumably in the realtime thread), but since we usually
1289
+ // don't know the hosts's block size beforehand, there's really nothing
1290
+ // else that we can do. Let's just hope that doing this once suffices,
1291
+ // then hopefully noone will notice.
1292
+ if (outbuf) {
1293
+ for (int i = 0; i < m; i++) {
1294
+ outbuf[i] = (float*)realloc(outbuf[i],
1295
+ blocksz*sizeof(float));
1296
+ assert(outbuf[i]);
1297
+ }
1298
+ }
1299
+ n_samples = blocksz;
1300
+ }
1301
+ if (outbuf) {
1302
+ // Polyphonic instrument: Mix the voices down to one signal.
1303
+ for (int i = 0; i < m; i++)
1304
+ for (unsigned j = 0; j < blocksz; j++)
1305
+ outputs[i][j] = 0.0f;
1306
+ for (int l = 0; l < nvoices; l++) {
1307
+ // Let Faust do all the hard work.
1308
+ dsp[l]->compute(blocksz, inputs, outbuf);
1309
+ for (int i = 0; i < m; i++)
1310
+ for (unsigned j = 0; j < blocksz; j++)
1311
+ outputs[i][j] += outbuf[i][j];
1312
+ }
1313
+ } else {
1314
+ // Simple effect: We can write directly to the output buffer.
1315
+ dsp[0]->compute(blocksz, inputs, outputs);
1316
+ }
1317
+ // Finally grab the passive controls and write them back to the
1318
+ // corresponding control ports. NOTE: Depending on the plugin
1319
+ // architecture, this might require a host call to get the control GUI
1320
+ // updated in real-time (if the host supports this at all).
1321
+ // FIXME: It's not clear how to aggregate the data of the different
1322
+ // voices. We compute the maximum of each control for now.
1323
+ if (n_out > 0) modified = true;
1324
+ for (int i = 0; i < n_out; i++) {
1325
+ int j = outctrls[i], k = ui[0]->elems[j].port;
1326
+ float *z = ui[0]->elems[j].zone;
1327
+ ports[k] = *z;
1328
+ for (int l = 1; l < nvoices; l++) {
1329
+ float *z = ui[l]->elems[j].zone;
1330
+ if (ports[k] < *z)
1331
+ ports[k] = *z;
1332
+ }
1333
+ }
1334
+ // Keep track of the last gates set for each voice, so that voices can be
1335
+ // forcibly retriggered if needed.
1336
+ if (gate >= 0)
1337
+ for (int i = 0; i < nvoices; i++)
1338
+ vd->lastgate[i] =
1339
+ *ui[i]->elems[gate].zone;
1340
+ }
1341
+
1342
+ // This processes just a single MIDI message, so to process an entire series
1343
+ // of MIDI events you'll have to loop over the event data in the plugin's
1344
+ // MIDI callback. XXXTODO: Sample-accurate processing of MIDI events.
1345
+
1346
+ void process_midi(unsigned char *data, int sz)
1347
+ {
1348
+ #if DEBUG_MIDI
1349
+ fprintf(stderr, "midi ev (%d bytes):", sz);
1350
+ for (int i = 0; i < sz; i++)
1351
+ fprintf(stderr, " 0x%0x", data[i]);
1352
+ fprintf(stderr, "\n");
1353
+ #endif
1354
+ uint8_t status = data[0] & 0xf0, chan = data[0] & 0x0f;
1355
+ bool is_instr = maxvoices > 0;
1356
+ switch (status) {
1357
+ case 0x90: {
1358
+ if (!is_instr) break;
1359
+ // note on
1360
+ #if DEBUG_NOTES
1361
+ fprintf(stderr, "note-on chan %d, note %d, vel %d\n", chan+1,
1362
+ data[1], data[2]);
1363
+ #endif
1364
+ if (data[2] == 0) goto note_off;
1365
+ alloc_voice(chan, data[1], data[2]);
1366
+ break;
1367
+ }
1368
+ case 0x80: {
1369
+ if (!is_instr) break;
1370
+ // note off
1371
+ #if DEBUG_NOTES
1372
+ fprintf(stderr, "note-off chan %d, note %d, vel %d\n", chan+1,
1373
+ data[1], data[2]);
1374
+ #endif
1375
+ note_off:
1376
+ dealloc_voice(chan, data[1], data[2]);
1377
+ break;
1378
+ }
1379
+ case 0xe0: {
1380
+ if (!is_instr) break;
1381
+ // pitch bend
1382
+ // data[1] is LSB, data[2] MSB, range is 0..0x3fff (which maps to
1383
+ // -2..+2 semitones by default), center point is 0x2000 = 8192
1384
+ int val = data[1] | (data[2]<<7);
1385
+ vd->bend[chan] =
1386
+ (val-0x2000)/8192.0f*vd->range[chan];
1387
+ #if DEBUG_MIDICC
1388
+ fprintf(stderr, "pitch-bend (chan %d): %g cent\n", chan+1,
1389
+ vd->bend[chan]*100.0);
1390
+ #endif
1391
+ update_voices(chan);
1392
+ break;
1393
+ }
1394
+ case 0xb0: {
1395
+ // controller change
1396
+ switch (data[1]) {
1397
+ case 120: case 123:
1398
+ if (!is_instr) break;
1399
+ // all-sound-off and all-notes-off controllers (these are treated
1400
+ // the same in the current implementation)
1401
+ all_notes_off(chan);
1402
+ #if DEBUG_MIDICC
1403
+ fprintf(stderr, "all-notes-off (chan %d)\n", chan+1);
1404
+ #endif
1405
+ break;
1406
+ case 121:
1407
+ // all-controllers-off (in the current implementation, this just
1408
+ // resets the RPN-related controllers)
1409
+ data_msb[chan] = data_lsb[chan] = 0;
1410
+ rpn_msb[chan] = rpn_lsb[chan] = 0x7f;
1411
+ #if DEBUG_MIDICC
1412
+ fprintf(stderr, "all-controllers-off (chan %d)\n", chan+1);
1413
+ #endif
1414
+ break;
1415
+ case 101: case 100:
1416
+ // RPN MSB/LSB
1417
+ if (data[1] == 101)
1418
+ rpn_msb[chan] = data[2];
1419
+ else
1420
+ rpn_lsb[chan] = data[2];
1421
+ break;
1422
+ case 6: case 38:
1423
+ // data entry coarse/fine
1424
+ if (data[1] == 6)
1425
+ data_msb[chan] = data[2];
1426
+ else
1427
+ data_lsb[chan] = data[2];
1428
+ goto rpn;
1429
+ case 96: case 97:
1430
+ // data increment/decrement
1431
+ /* NOTE: The specification of these controllers is a complete
1432
+ mess. Originally, the MIDI specification didn't have anything
1433
+ to say about their exact behaviour at all. Nowadays, the
1434
+ behaviour depends on which RPN or NRPN is being modified, which
1435
+ is also rather confusing. Fortunately, as we only handle RPNs
1436
+ 0..2 here anyway, it's sufficient to assume the MSB for RPN #2
1437
+ (channel coarse tuning) and the LSB otherwise. */
1438
+ if (rpn_msb[chan] == 0 && rpn_lsb[chan] == 2) {
1439
+ // modify the MSB
1440
+ if (data[1] == 96 && data_msb[chan] < 0x7f)
1441
+ data_msb[chan]++;
1442
+ else if (data[1] == 97 && data_msb[chan] > 0)
1443
+ data_msb[chan]--;
1444
+ } else {
1445
+ // modify the LSB
1446
+ if (data[1] == 96 && data_lsb[chan] < 0x7f)
1447
+ data_lsb[chan]++;
1448
+ else if (data[1] == 97 && data_lsb[chan] > 0)
1449
+ data_lsb[chan]--;
1450
+ }
1451
+ rpn:
1452
+ if (!is_instr) break;
1453
+ if (rpn_msb[chan] == 0) {
1454
+ switch (rpn_lsb[chan]) {
1455
+ case 0:
1456
+ // pitch bend range, coarse value is in semitones, fine value
1457
+ // in cents
1458
+ vd->range[chan] = data_msb[chan]+
1459
+ data_lsb[chan]/100.0;
1460
+ #if DEBUG_RPN
1461
+ fprintf(stderr, "pitch-bend-range (chan %d): %g cent\n", chan+1,
1462
+ vd->range[chan]*100.0);
1463
+ #endif
1464
+ break;
1465
+ case 1:
1466
+ {
1467
+ // channel fine tuning (14 bit value, range -100..+100 cents)
1468
+ int value = (data_msb[chan]<<7) |
1469
+ data_lsb[chan];
1470
+ vd->fine[chan] = (value-8192)/8192.0f;
1471
+ }
1472
+ goto master_tune;
1473
+ case 2:
1474
+ // channel coarse tuning (only msb is used, range -64..+63
1475
+ // semitones)
1476
+ vd->coarse[chan] = data_msb[chan]-64;
1477
+ master_tune:
1478
+ vd->tune[chan] = vd->coarse[chan]+
1479
+ vd->fine[chan];
1480
+ #if DEBUG_RPN
1481
+ fprintf(stderr, "master-tuning (chan %d): %g cent\n", chan+1,
1482
+ vd->tune[chan]*100.0);
1483
+ #endif
1484
+ update_voices(chan);
1485
+ break;
1486
+ default:
1487
+ break;
1488
+ }
1489
+ }
1490
+ break;
1491
+ default: {
1492
+ #if FAUST_MIDICC
1493
+ // interpret all other controller changes according to the MIDI
1494
+ // controller map defined in the Faust plugin itself
1495
+ std::map<uint8_t,int>::iterator it = ctrlmap.find(data[1]);
1496
+ if (it != ctrlmap.end()) {
1497
+ // defined MIDI controller
1498
+ int j = inctrls[it->second],
1499
+ k = ui[0]->elems[j].port;
1500
+ float val = ctrlval(ui[0]->elems[j], data[2]);
1501
+ midivals[chan][k] = val;
1502
+ if (is_instr) {
1503
+ // instrument: update running voices on this channel
1504
+ for (boost::circular_buffer<int>::iterator it =
1505
+ vd->used_voices.begin();
1506
+ it != vd->used_voices.end(); it++) {
1507
+ int i = *it;
1508
+ if (vd->note_info[i].ch == chan)
1509
+ *ui[i]->elems[j].zone = val;
1510
+ }
1511
+ } else {
1512
+ // simple effect: here we only have a single dsp instance and
1513
+ // we're operating in omni mode, so we just update the control no
1514
+ // matter what the midi channel is
1515
+ *ui[0]->elems[j].zone = val;
1516
+ }
1517
+ #if DEBUG_MIDICC
1518
+ fprintf(stderr, "ctrl-change chan %d, ctrl %d, val %d\n", chan+1,
1519
+ data[1], data[2]);
1520
+ #endif
1521
+ }
1522
+ #endif
1523
+ break;
1524
+ }
1525
+ }
1526
+ break;
1527
+ }
1528
+ default:
1529
+ break;
1530
+ }
1531
+ }
1532
+
1533
+ // Process an MTS sysex message and update the control values accordingly.
1534
+
1535
+ void process_sysex(uint8_t *data, int sz)
1536
+ {
1537
+ if (!data || sz < 2) return;
1538
+ #if DEBUG_MIDI
1539
+ fprintf(stderr, "midi sysex (%d bytes):", sz);
1540
+ for (int i = 0; i < sz; i++)
1541
+ fprintf(stderr, " 0x%0x", data[i]);
1542
+ fprintf(stderr, "\n");
1543
+ #endif
1544
+ if (data[0] == 0xf0) {
1545
+ // Skip over the f0 and f7 status bytes in case they are included in the
1546
+ // dump.
1547
+ data++; sz--;
1548
+ if (data[sz-1] == 0xf7) sz--;
1549
+ }
1550
+ if ((data[0] == 0x7e || data[0] == 0x7f) && data[2] == 8) {
1551
+ // MIDI tuning standard
1552
+ bool realtime = data[0] == 0x7f;
1553
+ if ((sz == 19 && data[3] == 8) ||
1554
+ (sz == 31 && data[3] == 9)) {
1555
+ // MTS scale/octave tuning 1- or 2-byte form
1556
+ bool onebyte = data[3] == 8;
1557
+ unsigned chanmsk = (data[4]<<14) | (data[5]<<7) | data[6];
1558
+ for (int i = 0; i < 12; i++) {
1559
+ float t;
1560
+ if (onebyte)
1561
+ t = (data[i+7]-64)/100.0;
1562
+ else
1563
+ t = (((data[2*i+7]<<7)|data[2*i+8])-8192)/8192.0;
1564
+ for (uint8_t ch = 0; ch < 16; ch++)
1565
+ if (chanmsk & (1<<ch))
1566
+ vd->tuning[ch][i] = t;
1567
+ }
1568
+ if (realtime) {
1569
+ for (uint8_t ch = 0; ch < 16; ch++)
1570
+ if (chanmsk & (1<<ch)) {
1571
+ // update running voices on this channel
1572
+ update_voices(ch);
1573
+ }
1574
+ }
1575
+ #if DEBUG_MTS
1576
+ fprintf(stderr, "octave-tuning-%s (chan ",
1577
+ realtime?"realtime":"non-realtime");
1578
+ bool first = true;
1579
+ for (uint8_t i = 0; i < 16; )
1580
+ if (chanmsk & (1<<i)) {
1581
+ uint8_t j;
1582
+ for (j = i+1; j < 16 && (chanmsk&(1<<j)); )
1583
+ j++;
1584
+ if (first)
1585
+ first = false;
1586
+ else
1587
+ fprintf(stderr, ",");
1588
+ if (j > i+1)
1589
+ fprintf(stderr, "%u-%u", i+1, j);
1590
+ else
1591
+ fprintf(stderr, "%u", i+1);
1592
+ i = j;
1593
+ } else
1594
+ i++;
1595
+ fprintf(stderr, "):");
1596
+ if (onebyte) {
1597
+ for (int i = 7; i < 19; i++) {
1598
+ int val = data[i];
1599
+ fprintf(stderr, " %d", val-64);
1600
+ }
1601
+ } else {
1602
+ for (int i = 7; i < 31; i++) {
1603
+ int val = data[i++] << 7;
1604
+ val |= data[i];
1605
+ fprintf(stderr, " %g", ((double)val-8192.0)/8192.0*100.0);
1606
+ }
1607
+ }
1608
+ fprintf(stderr, "\n");
1609
+ #endif
1610
+ }
1611
+ }
1612
+ }
1613
+
1614
+ // Change to a given preloaded tuning. The given tuning number may be in the
1615
+ // range 1..VSTPlugin::n_tunings, zero denotes the default tuning (equal
1616
+ // temperament). This is only supported if FAUST_MTS is defined at compile
1617
+ // time.
1618
+
1619
+ void change_tuning(int num)
1620
+ {
1621
+ #if FAUST_MTS
1622
+ if (!mts || num == tuning) return;
1623
+ modified = true;
1624
+ if (num < 0) num = 0;
1625
+ if (num > mts->tuning.size())
1626
+ num = mts->tuning.size();
1627
+ tuning = num;
1628
+ if (tuning > 0) {
1629
+ process_sysex(mts->tuning[tuning-1].data,
1630
+ mts->tuning[tuning-1].len);
1631
+ } else {
1632
+ memset(vd->tuning, 0, sizeof(vd->tuning));
1633
+ #if DEBUG_MTS
1634
+ fprintf(stderr,
1635
+ "octave-tuning-default (chan 1-16): equal temperament\n");
1636
+ #endif
1637
+ #endif
1638
+ }
1639
+ }
1640
+
1641
+ };
1642
+
1643
+ MyMeta *VSTPlugin::meta = 0;
1644
+ int VSTPlugin::n_tunings = 0;
1645
+ #if FAUST_MTS
1646
+ MTSTunings *VSTPlugin::mts = 0;
1647
+ #endif
1648
+
1649
+ /* VST-specific part starts here. ********************************************/
1650
+
1651
+ #include "audioeffectx.h"
1652
+ #if FAUST_UI
1653
+ #include "faustvstqt.h"
1654
+ #endif
1655
+
1656
+ /* NOTE: Some hosts are blacklisted here due to incompatibilities with the
1657
+ optional Qt GUI code. We include Ardour by default, but you may want to put
1658
+ other hosts on this list if they give you random crashes. You can also
1659
+ comment out the following define to enable the GUI in all hosts for testing
1660
+ purposes. Note that in any case the VST plugins *will* run in the
1661
+ blacklisted hosts, just without a custom GUI. */
1662
+ #define HOST_BLACKLIST { "Ardour", "REAPER", NULL }
1663
+ //#define HOST_BLACKLIST { "Ardour", "Tracktion", NULL }
1664
+
1665
+ class VSTWrapper : public AudioEffectX
1666
+ {
1667
+ public:
1668
+ VSTWrapper(audioMasterCallback audioMaster);
1669
+ ~VSTWrapper();
1670
+
1671
+ virtual void processReplacing(float **inputs, float **outputs,
1672
+ VstInt32 sampleframes);
1673
+ virtual VstInt32 processEvents(VstEvents* events);
1674
+
1675
+ virtual void suspend();
1676
+ virtual void resume();
1677
+ virtual void setSampleRate(float sampleRate);
1678
+
1679
+ virtual void setProgram(VstInt32 program);
1680
+ virtual void setProgramName(const char *name);
1681
+ virtual void getProgramName(char *name);
1682
+ virtual bool getProgramNameIndexed(VstInt32 category,
1683
+ VstInt32 index, char* text);
1684
+
1685
+ virtual void setParameter(VstInt32 index, float value);
1686
+ virtual float getParameter(VstInt32 index);
1687
+ virtual bool string2parameter(VstInt32 index, char *text);
1688
+ virtual void getParameterLabel(VstInt32 index, char *label);
1689
+ virtual void getParameterDisplay(VstInt32 index, char *text);
1690
+ virtual void getParameterName(VstInt32 index, char *text);
1691
+
1692
+ virtual VstInt32 getChunk(void** data,
1693
+ bool isPreset = false);
1694
+ virtual VstInt32 setChunk(void* data, VstInt32 byteSize,
1695
+ bool isPreset = false);
1696
+
1697
+ virtual bool getInputProperties(VstInt32 index,
1698
+ VstPinProperties *properties);
1699
+ virtual bool getOutputProperties(VstInt32 index,
1700
+ VstPinProperties* properties);
1701
+
1702
+ virtual bool getEffectName(char* name);
1703
+ virtual bool getVendorString(char* text);
1704
+ virtual bool getProductString(char* text);
1705
+ virtual VstInt32 getVendorVersion();
1706
+ virtual VstInt32 canDo(char* text);
1707
+
1708
+ // We process all MIDI channels on input.
1709
+ virtual VstInt32 getNumMidiInputChannels() { return 16; }
1710
+ // No MIDI output for now. XXXTODO: We might want to do MIDI controller
1711
+ // output for passive Faust controls in the future.
1712
+ virtual VstInt32 getNumMidiOutputChannels() { return 0; }
1713
+
1714
+ #if FAUST_UI
1715
+ // AG: Note that we have to map the GUI parameter numbers to the actual
1716
+ // Faust control indices here. This extra level of indirection is necessary
1717
+ // because in some cases Qt may enumerate the child widgets in a different
1718
+ // order than what we have in the Faust program. The mapping is computed in
1719
+ // the QTGUIWrapper class below, please see the comments there for details.
1720
+
1721
+ int n_params; // number of param mapping entries
1722
+ int *param_no; // map Qt -> Faust control numbers
1723
+ int *control_no; // map Faust -> Qt control numbers
1724
+
1725
+ int map_param(int i)
1726
+ {
1727
+ return (i < 0 || i >= n_params) ? i : param_no[i];
1728
+ }
1729
+
1730
+ int map_control(int i)
1731
+ {
1732
+ return (i < 0 || i >= n_params) ? i : control_no[i];
1733
+ }
1734
+
1735
+ // GUI-specific methods
1736
+ float getMinimum(VstInt32 index);
1737
+ float getMaximum(VstInt32 index);
1738
+ float getStep(VstInt32 index);
1739
+ int isPassiveControl(VstInt32 index);
1740
+ int getMaxVoices();
1741
+ int getNumTunings();
1742
+ int getNumControls();
1743
+ const char *getHostName();
1744
+ #else
1745
+ // Dummy versions to be used if the GUI is not included.
1746
+ int map_param(int i) { return i; }
1747
+ int map_control(int i) { return i; }
1748
+ #endif
1749
+
1750
+ private:
1751
+ VSTPlugin *plugin;
1752
+ char progname[kVstMaxProgNameLen+1];
1753
+ #if FAUST_UI
1754
+ char host[65];
1755
+ #endif
1756
+ float *progdata;
1757
+ };
1758
+
1759
+ // Create a "unique" VST plugin ID using Murmur2 hashes. This can't possibly
1760
+ // avoid all collisions, but will hopefully be good enough.
1761
+
1762
+ // Code pilfered from http://code.google.com/p/smhasher/.
1763
+ static uint32_t MurmurHash2(const void *key, int len, uint32_t seed)
1764
+ {
1765
+ // 'm' and 'r' are mixing constants generated offline.
1766
+ // They're not really 'magic', they just happen to work well.
1767
+
1768
+ const uint32_t m = 0x5bd1e995;
1769
+ const int r = 24;
1770
+
1771
+ // Initialize the hash to a 'random' value
1772
+
1773
+ uint32_t h = seed ^ len;
1774
+
1775
+ // Mix 4 bytes at a time into the hash
1776
+
1777
+ const unsigned char * data = (const unsigned char *)key;
1778
+
1779
+ while(len >= 4)
1780
+ {
1781
+ uint32_t k = *(uint32_t*)data;
1782
+
1783
+ k *= m;
1784
+ k ^= k >> r;
1785
+ k *= m;
1786
+
1787
+ h *= m;
1788
+ h ^= k;
1789
+
1790
+ data += 4;
1791
+ len -= 4;
1792
+ }
1793
+
1794
+ // Handle the last few bytes of the input array
1795
+
1796
+ switch(len)
1797
+ {
1798
+ case 3: h ^= data[2] << 16;
1799
+ case 2: h ^= data[1] << 8;
1800
+ case 1: h ^= data[0];
1801
+ h *= m;
1802
+ };
1803
+
1804
+ // Do a few final mixes of the hash to ensure the last few
1805
+ // bytes are well-incorporated.
1806
+
1807
+ h ^= h >> 13;
1808
+ h *= m;
1809
+ h ^= h >> 15;
1810
+
1811
+ return h;
1812
+ }
1813
+
1814
+ static uint32_t idhash(const char *s)
1815
+ {
1816
+ // Arbitrary seed value (should be the same for all instances).
1817
+ const uint32_t seed = 4711;
1818
+ // XXXFIXME: The rules for valid-formed VST ids don't seem to be very
1819
+ // clear. Can it be just any 32 bit number? But it looks like at least the
1820
+ // most significant bit should be 0 here, so we enforce that. (Some VST
1821
+ // hosts such as Carla display the id as zero otherwise.)
1822
+ return MurmurHash2(s, strlen(s), seed) & 0x7fffffff;
1823
+ }
1824
+
1825
+ // initialization and finalization
1826
+
1827
+ // This interface function is used by the code in vstplugmain.cpp to create an
1828
+ // instance of the plugin. It simply invokes the constructor of our VSTWrapper
1829
+ // class here.
1830
+ AudioEffect *createEffectInstance(audioMasterCallback audioMaster)
1831
+ {
1832
+ return new VSTWrapper(audioMaster);
1833
+ }
1834
+
1835
+ VSTWrapper::VSTWrapper(audioMasterCallback audioMaster)
1836
+ : AudioEffectX(audioMaster, 1, VSTPlugin::numControls())
1837
+ {
1838
+ const char *dsp_name = VSTPlugin::pluginName();
1839
+ const int num_voices = VSTPlugin::numVoices();
1840
+ // Get the initial sample rate from the VST host.
1841
+ const int rate = getSampleRate();
1842
+ plugin = new VSTPlugin(num_voices, rate);
1843
+ #if FAUST_UI
1844
+ // Get the name of the host (product string).
1845
+ strcpy(host, "Unknown");
1846
+ // Some hosts like Ardour properly report the product string even though
1847
+ // getHostProductString() returns false, so we just ignore the return value.
1848
+ getHostProductString(host);
1849
+ // Map of GUI parameter numbers to the actual control indices. This is
1850
+ // initialized later by VSTQtGUI::open() below.
1851
+ n_params = 0;
1852
+ param_no = control_no = 0;
1853
+ #endif
1854
+ // VST-specific initialization:
1855
+ if (audioMaster) {
1856
+ setNumInputs(plugin->dsp[0]->getNumInputs());
1857
+ setNumOutputs(plugin->dsp[0]->getNumOutputs());
1858
+ canProcessReplacing();
1859
+ programsAreChunks();
1860
+ if (plugin->maxvoices > 0) isSynth();
1861
+ // XXXFIXME: Maybe do something more clever for the unique id.
1862
+ setUniqueID((VstInt32)idhash(dsp_name));
1863
+
1864
+ #if FAUST_UI
1865
+ #ifdef HOST_BLACKLIST
1866
+ char *blacklist[] = HOST_BLACKLIST, **b = blacklist;
1867
+ while (*b && strcmp(host, *b)) ++b;
1868
+ //fprintf(stderr, "host '%s' is %s blacklist\n", host, *b?"on":"not on");
1869
+ if (!*b)
1870
+ #endif
1871
+ setEditor(new VSTQtGUI(this));
1872
+ #endif
1873
+ }
1874
+ // We only provide one "program" (a.k.a. built-in control preset), which
1875
+ // corresponds to the initial input control values in the Faust UI. Faust
1876
+ // has no built-in support for presets and we don't try to emulate that here
1877
+ // either. Most VST hosts will provide you with a way to save and restore
1878
+ // presets in a number of different formats, such as fxb and fxp files.
1879
+ curProgram = 0;
1880
+ setProgramName("Default");
1881
+ // Initialize the program storage. This is also used with getChunk/setChunk.
1882
+ // We reserve two extra entries for the instrument poly and tuning controls
1883
+ // here if needed.
1884
+ int k = plugin->ui[0]->nports;
1885
+ #if FAUST_MTS
1886
+ int m = (plugin->maxvoices > 0)?2:0;
1887
+ #else
1888
+ int m = (plugin->maxvoices > 0)?1:0;
1889
+ #endif
1890
+ progdata = (float*)calloc(k+m, sizeof(float));
1891
+ assert(k+m == 0 || progdata);
1892
+ // At this point, plugin->ports should already be filled with the initial
1893
+ // control values, use getChunk to copy them over to the program storage.
1894
+ void *data;
1895
+ (void)getChunk(&data);
1896
+ }
1897
+
1898
+ VSTWrapper::~VSTWrapper()
1899
+ {
1900
+ delete plugin;
1901
+ if (progdata) free(progdata);
1902
+ #if FAUST_UI
1903
+ if (param_no) delete[] param_no;
1904
+ if (control_no) delete[] control_no;
1905
+ #endif
1906
+ }
1907
+
1908
+ // plugin activation and deactivation
1909
+
1910
+ void VSTWrapper::suspend()
1911
+ {
1912
+ plugin->suspend();
1913
+ }
1914
+
1915
+ void VSTWrapper::resume()
1916
+ {
1917
+ plugin->rate = getSampleRate();
1918
+ plugin->resume();
1919
+ }
1920
+
1921
+ void VSTWrapper::setSampleRate(float sampleRate)
1922
+ {
1923
+ AudioEffect::setSampleRate(sampleRate);
1924
+ plugin->set_rate(sampleRate);
1925
+ }
1926
+
1927
+ // programs a.k.a. built-in presets (see above)
1928
+
1929
+ void VSTWrapper::setProgram(VstInt32 prog)
1930
+ {
1931
+ if (prog < 0 || prog >= 1) return;
1932
+ curProgram = prog;
1933
+ int k = plugin->ui[0]->nports;
1934
+ // instrument data size
1935
+ #if FAUST_MTS
1936
+ int m = (plugin->maxvoices > 0)?2:0;
1937
+ #else
1938
+ int m = (plugin->maxvoices > 0)?1:0;
1939
+ #endif
1940
+ (void)setChunk(progdata, (k+m)*sizeof(float));
1941
+ // Some hosts may require this to force a GUI update of the parameters.
1942
+ updateDisplay();
1943
+ }
1944
+
1945
+ void VSTWrapper::setProgramName(const char* name)
1946
+ {
1947
+ vst_strncpy(progname, name, kVstMaxProgNameLen);
1948
+ }
1949
+
1950
+ void VSTWrapper::getProgramName(char *name)
1951
+ {
1952
+ vst_strncpy(name, progname, kVstMaxProgNameLen);
1953
+ }
1954
+
1955
+ bool VSTWrapper::getProgramNameIndexed(VstInt32 category, VstInt32 index,
1956
+ char* text)
1957
+ {
1958
+ if (index < 1) {
1959
+ vst_strncpy(text, progname, kVstMaxProgNameLen);
1960
+ return true;
1961
+ } else
1962
+ return false;
1963
+ }
1964
+
1965
+ // control values (setters, getters, meta data)
1966
+
1967
+ VstInt32 VSTWrapper::getChunk(void** data, bool isPreset)
1968
+ {
1969
+ int k = plugin->ui[0]->nports;
1970
+ // data for the k ports is already in plugin->ports, for instruments we also
1971
+ // add the values of the polyphony and (if enabled) the tuning control
1972
+ memcpy(progdata, plugin->ports, k*sizeof(float));
1973
+ if (plugin->maxvoices > 0) {
1974
+ progdata[k++] = plugin->poly;
1975
+ #if FAUST_MTS
1976
+ progdata[k++] = plugin->tuning;
1977
+ #endif
1978
+ }
1979
+ *data = progdata;
1980
+ return k*sizeof(float);
1981
+ }
1982
+
1983
+ VstInt32 VSTWrapper::setChunk(void* data, VstInt32 byteSize, bool isPreset)
1984
+ {
1985
+ int k = plugin->ui[0]->nports, l = byteSize/sizeof(float);
1986
+ // instrument data size
1987
+ #if FAUST_MTS
1988
+ int m = (plugin->maxvoices > 0)?2:0;
1989
+ #else
1990
+ int m = (plugin->maxvoices > 0)?1:0;
1991
+ #endif
1992
+ if (byteSize != (k+m)*sizeof(float)) return 0; // data size mismatch
1993
+ // copy the data over to the program storage
1994
+ if (progdata != data) memcpy(progdata, data, (k+m)*sizeof(float));
1995
+ // set the control data
1996
+ memcpy(plugin->ports, progdata, k*sizeof(float));
1997
+ if (plugin->maxvoices > 0) {
1998
+ plugin->poly = min(plugin->maxvoices, max(1, (int)progdata[k]));
1999
+ #if FAUST_MTS
2000
+ plugin->change_tuning((int)progdata[k+1]);
2001
+ #endif
2002
+ }
2003
+ // Noone seems to know what the return value is good for. Just always
2004
+ // returning zero reportedly works with existing hosts.
2005
+ return 0;
2006
+ }
2007
+
2008
+ void VSTWrapper::getParameterName(VstInt32 index, char *label)
2009
+ {
2010
+ index = map_param(index);
2011
+ int k = plugin->ui[0]->nports;
2012
+ strcpy(label, "");
2013
+ if (index < k) {
2014
+ int j = plugin->ctrls[index];
2015
+ assert(index == plugin->ui[0]->elems[j].port);
2016
+ // Note that the VST spec mandates a maximum size of kVstMaxParamStrLen
2017
+ // for the label string, which is a rather small constant. This seems
2018
+ // overly restrictive, however, given that virtually all VST hosts provide
2019
+ // for much longer names. We allow 32 characters here which is hopefully
2020
+ // on the safe side.
2021
+ vst_strncpy(label, plugin->ui[0]->elems[j].label, 32);
2022
+ } else if (index == k && plugin->maxvoices > 0) {
2023
+ strcpy(label, "polyphony");
2024
+ #if FAUST_MTS
2025
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2026
+ strcpy(label, "tuning");
2027
+ #endif
2028
+ }
2029
+ }
2030
+
2031
+ void VSTWrapper::getParameterLabel(VstInt32 index, char *label)
2032
+ {
2033
+ index = map_param(index);
2034
+ int k = plugin->ui[0]->nports;
2035
+ strcpy(label, "");
2036
+ if (index < k) {
2037
+ int j = plugin->ctrls[index];
2038
+ assert(index == plugin->ui[0]->elems[j].port);
2039
+ if (plugin->units[index])
2040
+ // Allow for up to 32 characters; see the remarks concerning
2041
+ // kVstMaxParamStrLen above.
2042
+ vst_strncpy(label, plugin->units[index], 32);
2043
+ }
2044
+ }
2045
+
2046
+ // NOTE: VST parameters are always floats with unit range (0..1). So we need
2047
+ // to convert between Faust control values with given range/stepsize and the
2048
+ // VST range here. We use the following quantization algorithm for mapping VST
2049
+ // to Faust control values.
2050
+
2051
+ static double quantize(double x, double d)
2052
+ {
2053
+ if (d == 0.0) return x;
2054
+ // Round off x to the nearest increment of d. Note that this may produce
2055
+ // rounding artifacts if d is some power of 10 less than 0, since these
2056
+ // can't be represented exactly in binary.
2057
+ double i;
2058
+ if (x*d < 0.0)
2059
+ modf(x/d-0.5, &i);
2060
+ else
2061
+ modf(x/d+0.5, &i);
2062
+ return i*d;
2063
+ }
2064
+
2065
+ void VSTWrapper::getParameterDisplay(VstInt32 index, char *text)
2066
+ {
2067
+ index = map_param(index);
2068
+ int k = plugin->ui[0]->nports;
2069
+ strcpy(text, "");
2070
+ if (index < k) {
2071
+ int j = plugin->ctrls[index];
2072
+ assert(index == plugin->ui[0]->elems[j].port);
2073
+ sprintf(text, "%0.5g", plugin->ports[index]);
2074
+ } else if (index == k && plugin->maxvoices > 0) {
2075
+ sprintf(text, "%d voices", plugin->poly);
2076
+ #if FAUST_MTS
2077
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2078
+ sprintf(text, "%d %s", plugin->tuning,
2079
+ plugin->tuning>0?plugin->mts->tuning[plugin->tuning-1].name:
2080
+ "default");
2081
+ #endif
2082
+ }
2083
+ }
2084
+
2085
+ static inline float clamp(float min, float max, float val)
2086
+ {
2087
+ if (min<=max) {
2088
+ if (val < min) val = min;
2089
+ if (val > max) val = max;
2090
+ } else {
2091
+ if (val > min) val = min;
2092
+ if (val < max) val = max;
2093
+ }
2094
+ return val;
2095
+ }
2096
+
2097
+ float VSTWrapper::getParameter(VstInt32 index)
2098
+ {
2099
+ index = map_param(index);
2100
+ int k = plugin->ui[0]->nports;
2101
+ if (index >= 0 && index < k) {
2102
+ int j = plugin->ctrls[index];
2103
+ assert(index == plugin->ui[0]->elems[j].port);
2104
+ float min = plugin->ui[0]->elems[j].min;
2105
+ float max = plugin->ui[0]->elems[j].max;
2106
+ if (min == max)
2107
+ return 0.0f;
2108
+ else
2109
+ // Clamp the value to the 0..1 VST range. Some VST hosts (e.g., Carla)
2110
+ // don't like values falling outside that range.
2111
+ return clamp(0.0, 1.0, (plugin->ports[index]-min)/(max-min));
2112
+ } else if (index == k && plugin->maxvoices > 0) {
2113
+ return (float)plugin->poly/(float)plugin->maxvoices;
2114
+ #if FAUST_MTS
2115
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2116
+ return (float)plugin->tuning/(float)plugin->mts->tuning.size();
2117
+ #endif
2118
+ } else
2119
+ return 0.0f;
2120
+ }
2121
+
2122
+ void VSTWrapper::setParameter(VstInt32 index, float value)
2123
+ {
2124
+ index = map_param(index);
2125
+ const double eps = 1e-5;
2126
+ int k = plugin->ui[0]->nports;
2127
+ if (index >= 0 && index < k) {
2128
+ int j = plugin->ctrls[index];
2129
+ assert(index == plugin->ui[0]->elems[j].port);
2130
+ // XXXTODO: We use a rather simple-minded quantization algorithm here, do
2131
+ // something more comprehensive in the future.
2132
+ float min = plugin->ui[0]->elems[j].min;
2133
+ float max = plugin->ui[0]->elems[j].max;
2134
+ float step = plugin->ui[0]->elems[j].step;
2135
+ float val = (min == max)?min:min+quantize(value*(max-min), step);
2136
+ if (fabs(val) < fabs(step) || fabs(val)/fabs(max-min) < eps)
2137
+ val = 0.0;
2138
+ // We only need to update the port value here, the ui values are then
2139
+ // updated automatically as needed in the process_audio() callback.
2140
+ plugin->ports[index] = val;
2141
+ } else if (index == k && plugin->maxvoices > 0) {
2142
+ plugin->poly = (int)quantize((value*plugin->maxvoices), 1);
2143
+ if (plugin->poly <= 0) plugin->poly = 1;
2144
+ #if FAUST_MTS
2145
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2146
+ int tuning = (int)quantize((value*plugin->mts->tuning.size()), 1);
2147
+ plugin->change_tuning(tuning);
2148
+ #endif
2149
+ }
2150
+ }
2151
+
2152
+ bool VSTWrapper::string2parameter(VstInt32 index, char *text)
2153
+ {
2154
+ if (!text) return true;
2155
+ int k = plugin->ui[0]->nports;
2156
+ if (index >= 0 && index < k) {
2157
+ int j = plugin->ctrls[index];
2158
+ assert(index == plugin->ui[0]->elems[j].port);
2159
+ float min = plugin->ui[0]->elems[j].min;
2160
+ float max = plugin->ui[0]->elems[j].max;
2161
+ float step = plugin->ui[0]->elems[j].step;
2162
+ double val = atof(text);
2163
+ if (min == max)
2164
+ val = min;
2165
+ else
2166
+ val = min+quantize(val-min, step);
2167
+ if (min > max) {
2168
+ float m = max;
2169
+ max = min; min = m;
2170
+ }
2171
+ if (val < min)
2172
+ val = min;
2173
+ else if (val > max)
2174
+ val = max;
2175
+ plugin->ports[index] = val;
2176
+ } else if (index == k && plugin->maxvoices > 0) {
2177
+ int val = atoi(text);
2178
+ if (val <= 0) val = 1;
2179
+ if (val > plugin->maxvoices) val = plugin->maxvoices;
2180
+ plugin->poly = val;
2181
+ #if FAUST_MTS
2182
+ } else if (index == k+1 && plugin->mts &&
2183
+ plugin->mts->tuning.size() > 0) {
2184
+ plugin->change_tuning(atoi(text));
2185
+ #endif
2186
+ } else
2187
+ return false;
2188
+ return true;
2189
+ }
2190
+
2191
+ // audio inputs and outputs
2192
+
2193
+ bool VSTWrapper::getInputProperties(VstInt32 index,
2194
+ VstPinProperties* properties)
2195
+ {
2196
+ const char *dsp_name = VSTPlugin::pluginName();
2197
+ const int n = plugin->dsp[0]->getNumInputs();
2198
+ if (index < 0 || index >= n)
2199
+ return false;
2200
+ snprintf(properties->label, kVstMaxLabelLen,
2201
+ "%s input #%d", dsp_name, index);
2202
+ sprintf(properties->shortLabel, "In%d", index);
2203
+ properties->flags = kVstPinIsActive;
2204
+ // XXXTODO: deal with multi-channel setups (>2) here
2205
+ if (n == 2)
2206
+ properties->flags |= kVstPinIsStereo;
2207
+ return true;
2208
+ }
2209
+
2210
+ bool VSTWrapper::getOutputProperties(VstInt32 index,
2211
+ VstPinProperties* properties)
2212
+ {
2213
+ const char *dsp_name = VSTPlugin::pluginName();
2214
+ const int n = plugin->dsp[0]->getNumOutputs();
2215
+ if (index < 0 || index >= n)
2216
+ return false;
2217
+ snprintf(properties->label, kVstMaxLabelLen,
2218
+ "%s output #%d", dsp_name, index);
2219
+ sprintf(properties->shortLabel, "Out%d", index);
2220
+ properties->flags = kVstPinIsActive;
2221
+ // XXXTODO: deal with multi-channel setups (>2) here
2222
+ if (n == 2)
2223
+ properties->flags |= kVstPinIsStereo;
2224
+ return true;
2225
+ }
2226
+
2227
+ // global meta data
2228
+
2229
+ bool VSTWrapper::getEffectName(char *name)
2230
+ {
2231
+ const char *dsp_name = VSTPlugin::pluginName();
2232
+ vst_strncpy(name, dsp_name, kVstMaxEffectNameLen);
2233
+ return true;
2234
+ }
2235
+
2236
+ bool VSTWrapper::getVendorString(char *text)
2237
+ {
2238
+ const char *vendorString = VSTPlugin::pluginAuthor();
2239
+ vst_strncpy(text, vendorString, kVstMaxVendorStrLen);
2240
+ return true;
2241
+ }
2242
+
2243
+ bool VSTWrapper::getProductString(char *text)
2244
+ {
2245
+ const char *productString = VSTPlugin::pluginDescription();
2246
+ vst_strncpy(text, productString, kVstMaxProductStrLen);
2247
+ return true;
2248
+ }
2249
+
2250
+ VstInt32 VSTWrapper::getVendorVersion()
2251
+ {
2252
+ const char *versionString = VSTPlugin::pluginVersion();
2253
+ return (VstInt32)(atof(versionString)*1000.0);
2254
+ }
2255
+
2256
+ VstInt32 VSTWrapper::canDo(char *text)
2257
+ {
2258
+ if (strcmp(text, "receiveVstEvents") == 0) return 1;
2259
+ if (strcmp(text, "receiveVstMidiEvent") == 0) return 1;
2260
+ // This may convince some VST hosts to send us sysex events (seems to be
2261
+ // supported by some Bitwig versions at least).
2262
+ if (strcmp(text, "receiveVstSysexEvent") == 0) return 1;
2263
+ return -1;
2264
+ }
2265
+
2266
+ // audio and MIDI process functions
2267
+
2268
+ void VSTWrapper::processReplacing(float **inputs, float **outputs,
2269
+ VstInt32 n_samples)
2270
+ {
2271
+ plugin->process_audio(n_samples, inputs, outputs);
2272
+ // Some hosts may require this to force a GUI update of the controls.
2273
+ // XXXFIXME: Alas, some hosts don't seem to handle this at all (e.g.,
2274
+ // Tracktion).
2275
+ if (plugin->modified) updateDisplay();
2276
+ }
2277
+
2278
+ VstInt32 VSTWrapper::processEvents(VstEvents* events)
2279
+ {
2280
+ // Process incoming MIDI events.
2281
+ for (VstInt32 i = 0; i < events->numEvents; i++) {
2282
+ if (events->events[i]->type == kVstMidiType) {
2283
+ VstMidiEvent* ev = (VstMidiEvent*)events->events[i];
2284
+ uint8_t *data = (uint8_t*)ev->midiData;
2285
+ #if 0
2286
+ // FIXME: Consider doing sample-accurate note onsets here. VST keeps
2287
+ // track of the exact onset in the deltaFrames field, but we can't use
2288
+ // that information at present, since our gate parameter is a control
2289
+ // variable which can only change at block boundaries. In the future,
2290
+ // the gate could be implemented as an audio signal to get
2291
+ // sample-accurate note onsets.
2292
+ VstInt32 frames = ev->deltaFrames;
2293
+ #endif
2294
+ #if 0
2295
+ fprintf(stderr, "ev length = %d, offset = %d, detune = %d, off velocity = %d\n", ev->noteLength, ev->noteOffset, (int)(signed char)ev->detune, (int)ev->noteOffVelocity);
2296
+ #endif
2297
+ plugin->process_midi(data, 4);
2298
+ } else if (events->events[i]->type == kVstSysExType) {
2299
+ VstMidiSysexEvent* ev = (VstMidiSysexEvent*)events->events[i];
2300
+ int sz = ev->dumpBytes;
2301
+ uint8_t *data = (uint8_t*)ev->sysexDump;
2302
+ bool is_instr = plugin->maxvoices > 0;
2303
+ if (!is_instr) continue;
2304
+ plugin->process_sysex(data, sz);
2305
+ } else {
2306
+ fprintf(stderr, "%s: unknown event type %d\n",
2307
+ VSTPlugin::pluginName(), events->events[i]->type);
2308
+ }
2309
+ }
2310
+ return 1;
2311
+ }
2312
+
2313
+ #if FAUST_UI
2314
+
2315
+ /* Qt-specific part starts here. *********************************************/
2316
+
2317
+ /* Copyright (c) 2015-2016 by Roman Svidler (rosvid). Some improvements and
2318
+ HTTPD/OSC support added by Albert Gräf (ag). Distributed under the LGPLv3+.
2319
+ Original code is available at https://github.com/rosvid/faust-vst-qt. */
2320
+
2321
+ // special getters needed by the GUI code
2322
+
2323
+ float VSTWrapper::getMinimum(VstInt32 index)
2324
+ {
2325
+ index = map_param(index);
2326
+ int k = plugin->ui[0]->nports;
2327
+ if (index < 0)
2328
+ return 0.0f;
2329
+ else if (index < k) {
2330
+ int j = plugin->ctrls[index];
2331
+ assert(index == plugin->ui[0]->elems[j].port);
2332
+ float min = plugin->ui[0]->elems[j].min;
2333
+ return min;
2334
+ } else if (index == k && plugin->maxvoices > 0) {
2335
+ return 0.0f;
2336
+ #if FAUST_MTS
2337
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2338
+ return 0.0f;
2339
+ #endif
2340
+ } else
2341
+ return 0.0f;
2342
+ }
2343
+
2344
+ float VSTWrapper::getMaximum(VstInt32 index)
2345
+ {
2346
+ index = map_param(index);
2347
+ int k = plugin->ui[0]->nports;
2348
+ if (index < 0)
2349
+ return 0.0f;
2350
+ else if (index < k) {
2351
+ int j = plugin->ctrls[index];
2352
+ assert(index == plugin->ui[0]->elems[j].port);
2353
+ float max = plugin->ui[0]->elems[j].max;
2354
+ return max;
2355
+ } else if (index == k && plugin->maxvoices > 0) {
2356
+ return (float)plugin->maxvoices;
2357
+ #if FAUST_MTS
2358
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2359
+ return (float)plugin->mts->tuning.size();
2360
+ #endif
2361
+ } else
2362
+ return 0.0f;
2363
+ }
2364
+
2365
+ float VSTWrapper::getStep(VstInt32 index)
2366
+ {
2367
+ index = map_param(index);
2368
+ int k = plugin->ui[0]->nports;
2369
+ if (index < 0)
2370
+ return 0.0f;
2371
+ else if (index < k) {
2372
+ int j = plugin->ctrls[index];
2373
+ assert(index == plugin->ui[0]->elems[j].port);
2374
+ float step = plugin->ui[0]->elems[j].step;
2375
+ return step;
2376
+ } else if (index == k && plugin->maxvoices > 0) {
2377
+ return 1.0f;
2378
+ #if FAUST_MTS
2379
+ } else if (index == k+1 && plugin->n_tunings > 0) {
2380
+ return 1.0f;
2381
+ #endif
2382
+ } else
2383
+ return 0.0f;
2384
+ }
2385
+
2386
+ int VSTWrapper::isPassiveControl(VstInt32 index)
2387
+ {
2388
+ index = map_param(index);
2389
+ int k = plugin->ui[0]->nports;
2390
+ if (index >= 0 && index < k) {
2391
+ int j = plugin->ctrls[index];
2392
+ assert(index == plugin->ui[0]->elems[j].port);
2393
+ switch (plugin->ui[0]->elems[j].type) {
2394
+ case UI_V_BARGRAPH:
2395
+ return 1; // passive control is of type UI_V_BARGRAPH
2396
+ case UI_H_BARGRAPH:
2397
+ return 2; // passive control is of type UI_H_BARGRAPH
2398
+ default:
2399
+ return 0; // not a passive control
2400
+ }
2401
+ } else
2402
+ return 0;
2403
+ }
2404
+
2405
+ int VSTWrapper::getMaxVoices()
2406
+ {
2407
+ return plugin->maxvoices;
2408
+ }
2409
+
2410
+ int VSTWrapper::getNumTunings()
2411
+ {
2412
+ #if FAUST_MTS
2413
+ return plugin->n_tunings;
2414
+ #else
2415
+ return 0;
2416
+ #endif
2417
+ }
2418
+
2419
+ int VSTWrapper::getNumControls()
2420
+ {
2421
+ return plugin->ui[0]->nports;;
2422
+ }
2423
+
2424
+ const char *VSTWrapper::getHostName()
2425
+ {
2426
+ return host;
2427
+ }
2428
+
2429
+ // OSCUI.h and httpdUI.h pull in their own definition of the Meta struct,
2430
+ // prevent name clashes with our version.
2431
+ #define Meta FaustMeta
2432
+
2433
+ #include <iostream>
2434
+ #include <QApplication>
2435
+ #include <faust/gui/QTUI.h>
2436
+ #ifdef OSCCTRL
2437
+ #include <faust/gui/OSCUI.h>
2438
+ #endif
2439
+ #ifdef HTTPCTRL
2440
+ #include <faust/gui/httpdUI.h>
2441
+ #endif
2442
+
2443
+ #include <QWidget>
2444
+ #include <QList>
2445
+ #include <QtAlgorithms>
2446
+ #include <QX11Info>
2447
+ #include <X11/Xlib.h>
2448
+
2449
+ #line 2438 "faustvst.cpp"
2450
+
2451
+ std::list<GUI*> GUI::fGuiList;
2452
+ ztimedmap GUI::gTimedZoneMap;
2453
+
2454
+ /* Define this to get debugging output from the Qt-related code, or add the
2455
+ corresponding option to the qmake project options in the faust2faustvstqt
2456
+ script to achieve the same effect. Setting this to a value >1 will give
2457
+ even more extensive debugging output. Using a zero value or commenting the
2458
+ following line makes sure that no qDebug calls are included in the code at
2459
+ all. -ag */
2460
+ //#define FAUSTQT_DEBUG 1
2461
+
2462
+ /**
2463
+ * @brief VSTQtGUI::VSTQtGUI
2464
+ * - initializations that need to be done when creating an editor object
2465
+ * (make sure that the QApplication is initialized if needed)
2466
+ * @param effect
2467
+ */
2468
+ VSTQtGUI::VSTQtGUI(VSTWrapper* effect) : effect(effect),
2469
+ widget(NULL), uidsp(NULL),
2470
+ #ifdef OSCCTRL
2471
+ oscinterface(NULL),
2472
+ #endif
2473
+ #ifdef HTTPCTRL
2474
+ httpdinterface(NULL),
2475
+ #endif
2476
+ qtinterface(NULL)
2477
+ {
2478
+ static int argc = 0;
2479
+ static char* argv[1] = {0};
2480
+ if(qApp) {
2481
+ #if FAUSTQT_DEBUG
2482
+ qDebug() << "qApp already exists";
2483
+ #endif
2484
+ } else {
2485
+ #if FAUSTQT_DEBUG
2486
+ qDebug() << "qApp is created!";
2487
+ #endif
2488
+ new QApplication(argc, argv);
2489
+ }
2490
+
2491
+ int n_controls = effect->getNumControls();
2492
+ // instruments can have up to 2 controls more (poly+tuning)
2493
+ if (effect->getMaxVoices()>0) n_controls += 2;
2494
+ // this array is used to keep track of the current status of control values;
2495
+ // GUI controls are only set if the value has changed
2496
+ control_values = (float*)calloc(n_controls, sizeof(float));
2497
+
2498
+ #if FAUSTQT_DEBUG
2499
+ qDebug() << "qApp=" << qApp;
2500
+ static bool first_time = false;
2501
+ if (!first_time) {
2502
+ first_time = true;
2503
+ qDebug() << "VST host: " << effect->getHostName();
2504
+ }
2505
+ #endif
2506
+ }
2507
+
2508
+ /**
2509
+ * @brief VSTQtGUI::~VSTQtGUI
2510
+ * - finalizations that need to be done when destroying an editor object
2511
+ */
2512
+ VSTQtGUI::~VSTQtGUI()
2513
+ {
2514
+ if (control_values) free(control_values);
2515
+ }
2516
+
2517
+ // This is a little wrapper class around QTGUI which takes care of eliminating
2518
+ // the freq/gain/gate controls of instruments in the user interface when
2519
+ // running the dsp's buildUserInterface method. It also adds polyphony and
2520
+ // tuning controls to instruments as needed, and does some other extra
2521
+ // bookkeeping and on-the-fly modifications that we need. -ag
2522
+
2523
+ // AG XXXFIXME: This is more complicated than we'd like it to be, since for
2524
+ // some unknown reason, the children of a tab widget are listed in reverse
2525
+ // order (https://bitbucket.org/agraef/faust-lv2/issues/10). Since the GUI
2526
+ // code assumes that the widgets are in the same order as the Faust control
2527
+ // elements, we need to construct a mapping that translates between the two.
2528
+
2529
+ struct QTGUIElem {
2530
+ int i;
2531
+ QList<int> p;
2532
+ const char *label;
2533
+ QTGUIElem(int _i, QList<int> _p, const char *_label) :
2534
+ i(_i), p(_p), label(_label)
2535
+ {}
2536
+ };
2537
+
2538
+ bool qtguielem_less(const QTGUIElem &x, const QTGUIElem &y)
2539
+ {
2540
+ // Qt4 doesn't define operator< on QLists, so we need to do the
2541
+ // lexicographic comparison manually.
2542
+ QList<int>::const_iterator i = x.p.begin(), j = y.p.begin();
2543
+ for (; i != x.p.end() && j != y.p.end(); ++i, ++j) {
2544
+ if (*i < *j)
2545
+ return true;
2546
+ else if (*i > *j)
2547
+ return false;
2548
+ }
2549
+ return j != y.p.end();
2550
+ }
2551
+
2552
+ class QTGUIWrapper : public UI
2553
+ {
2554
+ protected:
2555
+ bool is_instr;
2556
+ QTGUI *ui;
2557
+ QList<int> path;
2558
+ QList<QTGUIElem> elems;
2559
+ int level, maxvoices, numtunings;
2560
+ float *voices_zone, *tuning_zone;
2561
+ bool have_freq, have_gain, have_gate;
2562
+ bool is_voice_ctrl(const char *label)
2563
+ {
2564
+ if (!is_instr)
2565
+ return false;
2566
+ else if (!have_freq && !strcmp(label, "freq"))
2567
+ return (have_freq = true);
2568
+ else if (!have_gain && !strcmp(label, "gain"))
2569
+ return (have_gain = true);
2570
+ else if (!have_gate && !strcmp(label, "gate"))
2571
+ return (have_gate = true);
2572
+ else
2573
+ return false;
2574
+ }
2575
+ public:
2576
+ int *elem_no;
2577
+ int nelems;
2578
+ QTGUIWrapper(QTGUI *_ui, int _maxvoices, int _numtunings,
2579
+ float *_voices_zone, float *_tuning_zone) :
2580
+ is_instr(_maxvoices>0), ui(_ui), level(0),
2581
+ maxvoices(_maxvoices), numtunings(_numtunings),
2582
+ voices_zone(_voices_zone), tuning_zone(_tuning_zone),
2583
+ have_freq(false), have_gain(false), have_gate(false),
2584
+ elem_no(0), nelems(0)
2585
+ {}
2586
+ virtual ~QTGUIWrapper() {}
2587
+
2588
+ // -- widget's layouts
2589
+ virtual void openTabBox(const char* label)
2590
+ { ui->openTabBox(label); level++; path.append(-1); }
2591
+ virtual void openHorizontalBox(const char* label)
2592
+ { ui->openHorizontalBox(label); level++; path.append(0); }
2593
+ virtual void openVerticalBox(const char* label)
2594
+ { ui->openVerticalBox(label); level++; path.append(0); }
2595
+ virtual void closeBox()
2596
+ {
2597
+ if (--level == 0) {
2598
+ #if VOICE_CTRLS
2599
+ if (is_instr) {
2600
+ // Add polyphony and tuning controls (experimental).
2601
+ ui->addHorizontalSlider("polyphony", voices_zone,
2602
+ maxvoices/2, 0, maxvoices, 1);
2603
+ addElem("Polyphony");
2604
+ #if FAUST_MTS
2605
+ if (numtunings>0)
2606
+ ui->addHorizontalSlider("tuning", tuning_zone, 0, 0, numtunings, 1);
2607
+ addElem("Tuning");
2608
+ #endif
2609
+ }
2610
+ #endif
2611
+ // AG: Create an index of all the GUI elements in the right order.
2612
+ // XXXFIXME: This may need to be revisited if Qt or Faust changes the
2613
+ // order for some reason.
2614
+ qSort(elems.begin(), elems.end(), qtguielem_less);
2615
+ elem_no = new int[nelems];
2616
+ nelems = 0;
2617
+ for (QList<QTGUIElem>::iterator x = elems.begin(); x != elems.end();
2618
+ ++x, ++nelems) {
2619
+ elem_no[nelems] = x->i;
2620
+ #if 0
2621
+ fprintf(stderr, "%s (#%d):", x->label, x->i);
2622
+ for (QList<int>::iterator i = x->p.begin(); i != x->p.end(); ++i) {
2623
+ fprintf(stderr, " %d", *i);
2624
+ }
2625
+ fprintf(stderr, "\n");
2626
+ #endif
2627
+ }
2628
+ }
2629
+ path.pop_back();
2630
+ if (!path.empty()) {
2631
+ if (path.last() < 0)
2632
+ path.last()--;
2633
+ else
2634
+ path.last()++;
2635
+ }
2636
+ ui->closeBox();
2637
+ }
2638
+
2639
+ void addElem(const char *label)
2640
+ {
2641
+ elems.append(QTGUIElem(nelems++, path, label));
2642
+ assert(!path.empty());
2643
+ if (path.last() < 0)
2644
+ path.last()--;
2645
+ else
2646
+ path.last()++;
2647
+ }
2648
+
2649
+ // -- active widgets
2650
+ virtual void addButton(const char* label, FAUSTFLOAT* zone)
2651
+ {
2652
+ if (!is_voice_ctrl(label)) {
2653
+ ui->addButton(label, zone);
2654
+ addElem(label);
2655
+ }
2656
+ }
2657
+ virtual void addCheckButton(const char* label, FAUSTFLOAT* zone)
2658
+ {
2659
+ if (!is_voice_ctrl(label)) {
2660
+ ui->addCheckButton(label, zone);
2661
+ addElem(label);
2662
+ }
2663
+ }
2664
+ virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone,
2665
+ FAUSTFLOAT init, FAUSTFLOAT min,
2666
+ FAUSTFLOAT max, FAUSTFLOAT step)
2667
+ {
2668
+ if (!is_voice_ctrl(label)) {
2669
+ ui->addVerticalSlider(label, zone, init, min, max, step);
2670
+ addElem(label);
2671
+ }
2672
+ }
2673
+ virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone,
2674
+ FAUSTFLOAT init, FAUSTFLOAT min,
2675
+ FAUSTFLOAT max, FAUSTFLOAT step)
2676
+ {
2677
+ if (!is_voice_ctrl(label)) {
2678
+ ui->addHorizontalSlider(label, zone, init, min, max, step);
2679
+ addElem(label);
2680
+ }
2681
+ }
2682
+ virtual void addNumEntry(const char* label, FAUSTFLOAT* zone,
2683
+ FAUSTFLOAT init, FAUSTFLOAT min,
2684
+ FAUSTFLOAT max, FAUSTFLOAT step)
2685
+ {
2686
+ if (!is_voice_ctrl(label)) {
2687
+ ui->addNumEntry(label, zone, init, min, max, step);
2688
+ addElem(label);
2689
+ }
2690
+ }
2691
+
2692
+ // -- passive widgets
2693
+ virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone,
2694
+ FAUSTFLOAT min, FAUSTFLOAT max)
2695
+ {
2696
+ ui->addHorizontalBargraph(label, zone, min, max);
2697
+ addElem(label);
2698
+ }
2699
+ virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone,
2700
+ FAUSTFLOAT min, FAUSTFLOAT max)
2701
+ {
2702
+ ui->addVerticalBargraph(label, zone, min, max);
2703
+ addElem(label);
2704
+ }
2705
+
2706
+ virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
2707
+
2708
+ virtual void declare(FAUSTFLOAT* zone, const char* key, const char* val)
2709
+ {
2710
+ // XXXFIXME: Faust's Qt GUI implementation handles [scale:log] and similar
2711
+ // meta data affecting the scaling of slider data, but this isn't
2712
+ // supported in the current faust-vst implementation, so we just ignore
2713
+ // this meta data for now.
2714
+ if (strcmp(key, "scale")) ui->declare(zone, key, val);
2715
+ }
2716
+
2717
+ };
2718
+
2719
+ /**
2720
+ * @brief VSTQtGUI::open
2721
+ * - method to open the plug-in GUI
2722
+ * - the GUI is generated through QTUI.h (QTGUI() class)
2723
+ * - communication between GUI elements and the corresponding VST parameters
2724
+ * is realized using Qt's signal-slot mechanism
2725
+ * @param ptr
2726
+ * @return
2727
+ */
2728
+ bool VSTQtGUI::open(void *ptr)
2729
+ {
2730
+ static int argc = 0;
2731
+ static char* argv[1] = {0};
2732
+ #if FAUSTQT_DEBUG
2733
+ qDebug() << "open editor: " << ptr;
2734
+ #endif
2735
+ AEffEditor::open(ptr);
2736
+
2737
+ widget = new QScrollArea();
2738
+ widget->setWidgetResizable(true);
2739
+ qtinterface = new QTGUI(widget);
2740
+ widget->setWidget(qtinterface);
2741
+
2742
+ mydsp* dsp = new mydsp();
2743
+
2744
+ #if FAUSTQT_DEBUG
2745
+ qDebug() << "open interface: " << qtinterface;
2746
+ #endif
2747
+ // We build the QTGUI indirectly through QTGUIWrapper whose sole purpose is
2748
+ // to eliminate the voice controls in case of an instrument plugin.
2749
+ QTGUIWrapper qtwrapper(qtinterface,
2750
+ effect->getMaxVoices(), effect->getNumTunings(),
2751
+ &voices_zone, &tuning_zone);
2752
+ dsp->buildUserInterface(&qtwrapper);
2753
+
2754
+ // AG: Initialize the Qt GUI -> Faust UI mapping (see the explanation under
2755
+ // QTGUIWrapper above).
2756
+ effect->n_params = qtwrapper.nelems;
2757
+ effect->param_no = qtwrapper.elem_no;
2758
+ effect->control_no = new int[qtwrapper.nelems];
2759
+ for (int i = 0; i < qtwrapper.nelems; i++)
2760
+ effect->control_no[effect->param_no[i]] = i;
2761
+ #if 0
2762
+ for (int i = 0; i < effect->n_params; i++)
2763
+ fprintf(stderr, "QT->LV2 %d -> %d\n", i, effect->param_no[i]);
2764
+ for (int i = 0; i < effect->n_params; i++)
2765
+ fprintf(stderr, "LV2->QT %d -> %d\n", i, effect->control_no[i]);
2766
+ #endif
2767
+
2768
+ // HTTPD and OSC support (experimental)
2769
+ #ifdef HTTPCTRL
2770
+ httpdinterface = new httpdUI(VSTPlugin::pluginName(),
2771
+ dsp->getNumInputs(), dsp->getNumOutputs(),
2772
+ argc, argv);
2773
+ dsp->buildUserInterface(httpdinterface);
2774
+ #if FAUSTQT_DEBUG
2775
+ qDebug() << "HTTPD is on";
2776
+ #endif
2777
+ #endif
2778
+
2779
+ #ifdef OSCCTRL
2780
+ oscinterface = new OSCUI(VSTPlugin::pluginName(), argc, argv);
2781
+ dsp->buildUserInterface(oscinterface);
2782
+ #if FAUSTQT_DEBUG
2783
+ qDebug() << "OSC is on";
2784
+ #endif
2785
+ #endif
2786
+
2787
+ // update the size of the QTGUI after creating the GUI elements
2788
+ qtinterface->adjustSize();
2789
+
2790
+ // the dimensions of the plug-in window must not exceed screenGeometry
2791
+ // (-80 pixel tolerance)
2792
+ int desktopHeight = QApplication::desktop()->screenGeometry().height()-80;
2793
+ int desktopWidth = QApplication::desktop()->screenGeometry().width()-80;
2794
+
2795
+ #if FAUSTQT_DEBUG>1
2796
+ qDebug() << "desktop-height: " <<
2797
+ QApplication::desktop()->screenGeometry().height();
2798
+ qDebug() << "desktop-width: " <<
2799
+ QApplication::desktop()->screenGeometry().width();
2800
+ #endif
2801
+
2802
+ // determine the window size
2803
+ rectangle.top = 0;
2804
+ rectangle.left = 0;
2805
+ // the height of the plug-in GUI must not exceed the desktop resolution
2806
+ if(qtinterface->height() > desktopHeight)
2807
+ rectangle.bottom = desktopHeight;
2808
+ else // add 20 pixels for scroll bars
2809
+ rectangle.bottom = qtinterface->height()+20;
2810
+ // the width of the plug-in GUI must not exceed the desktop resolution
2811
+ if(qtinterface->width() > desktopWidth)
2812
+ rectangle.right = desktopWidth;
2813
+ else // add 20 pixels for scroll bars
2814
+ rectangle.right = qtinterface->width()+20;
2815
+
2816
+ // adjust the widget size
2817
+ widget->resize(rectangle.right, rectangle.bottom);
2818
+ // some hosts (e.g., Qtractor) need this to properly adjust the window size
2819
+ effect->sizeWindow(rectangle.right, rectangle.bottom);
2820
+
2821
+ // determine all children of qtinterface of type QObject*
2822
+ QList<QObject*> allObjects = qtinterface->findChildren<QObject*>();
2823
+ #if FAUSTQT_DEBUG>1
2824
+ qDebug() << "QObjects total count: " << allObjects.count();
2825
+ #endif
2826
+
2827
+ int vstParamCount = 0;
2828
+
2829
+ bool vBargraphChecked = true; // used in HorizontalBargraph search
2830
+ QObject* lastObject; // used in addNumDisplay check
2831
+
2832
+ for (QList<QObject*>::iterator i = allObjects.begin(); i != allObjects.end();
2833
+ ++i) {
2834
+ #if FAUSTQT_DEBUG>1
2835
+ qDebug("");
2836
+ // debugging output: class name of found object
2837
+ qDebug() << "QObject: " << (*i)->metaObject()->className();
2838
+ qDebug() << "VST parameter assigned: " << vstParamCount;
2839
+ #endif
2840
+
2841
+ // Slider
2842
+ QSlider* slider = qobject_cast<QSlider*>(*i);
2843
+ if (slider) {
2844
+ #if FAUSTQT_DEBUG>1
2845
+ qDebug("found slider!");
2846
+ #endif
2847
+ slider->setProperty("vstParam", vstParamCount);
2848
+ QList<QObject*> c; c.append(slider);
2849
+ controls.append(c);
2850
+
2851
+ connect(slider, SIGNAL(valueChanged(int)), this, SLOT(updateVST()),
2852
+ Qt::QueuedConnection);
2853
+ updateQTGUI(slider, effect->getParameter(vstParamCount));
2854
+
2855
+ vstParamCount++;
2856
+ }
2857
+
2858
+ // Knob
2859
+ QDial* dial = qobject_cast<QDial*>(*i);
2860
+ if (dial) {
2861
+ #if FAUSTQT_DEBUG>1
2862
+ qDebug("found knob!");
2863
+ #endif
2864
+ dial->setProperty("vstParam", vstParamCount);
2865
+ QList<QObject*> c; c.append(dial);
2866
+ controls.append(c);
2867
+
2868
+ connect(dial, SIGNAL(valueChanged(int)), this, SLOT(updateVST()),
2869
+ Qt::QueuedConnection);
2870
+ updateQTGUI(dial, effect->getParameter(vstParamCount));
2871
+
2872
+ vstParamCount++;
2873
+ }
2874
+
2875
+ // Button
2876
+ QPushButton* button = qobject_cast<QPushButton*>(*i);
2877
+ if (button) {
2878
+ #if FAUSTQT_DEBUG>1
2879
+ qDebug("found button!");
2880
+ #endif
2881
+ button->setProperty("vstParam", vstParamCount);
2882
+ QList<QObject*> c; c.append(button);
2883
+ controls.append(c);
2884
+
2885
+ connect(button, SIGNAL(pressed()), this,
2886
+ SLOT(updateVST_buttonPressed()), Qt::QueuedConnection);
2887
+ connect(button, SIGNAL(released()), this,
2888
+ SLOT(updateVST_buttonReleased()), Qt::QueuedConnection);
2889
+
2890
+ // button is released when GUI opens
2891
+ effect->setParameter(vstParamCount, 0.0f);
2892
+ control_values[vstParamCount] = 0.0f;
2893
+
2894
+ vstParamCount++;
2895
+ }
2896
+
2897
+ // NumDisplay (list) / NumEntry / numerical HorizontalBargraph
2898
+ QDoubleSpinBox* num = qobject_cast<QDoubleSpinBox*>(*i);
2899
+ if (num) {
2900
+ // ignore QDoubleSpinBox with NoButtons, as it's not a list but
2901
+ // a NumDisplay
2902
+ if(num->buttonSymbols() != QAbstractSpinBox::NoButtons) {
2903
+ #if FAUSTQT_DEBUG>1
2904
+ qDebug("found list!");
2905
+ #endif
2906
+ num->setProperty("vstParam", vstParamCount);
2907
+ QList<QObject*> c; c.append(num);
2908
+ controls.append(c);
2909
+
2910
+ connect(num, SIGNAL(valueChanged(double)), this, SLOT(updateVST()),
2911
+ Qt::QueuedConnection);
2912
+
2913
+ updateQTGUI(num, effect->getParameter(vstParamCount));
2914
+
2915
+ vstParamCount++;
2916
+
2917
+ // if previous control is passive and vBargraphChecked==false:
2918
+ // found NumDisplay of VerticalBargraphs
2919
+ // this is always called if we found a vBargraph in the previous
2920
+ // iteration
2921
+ } else if(effect->isPassiveControl(vstParamCount-1)==1
2922
+ && !vBargraphChecked) {
2923
+ #if FAUSTQT_DEBUG>1
2924
+ qDebug("found numDisplay!");
2925
+ #endif
2926
+ num->setProperty("vstParam", vstParamCount-1);
2927
+ controls[vstParamCount-1].append(num);
2928
+ passive_controls.append(num);
2929
+
2930
+ // the corresponding display of the vBargraphs is now set
2931
+ vBargraphChecked = true;
2932
+ } else if(vstParamCount < effect->n_params &&
2933
+ effect->isPassiveControl(vstParamCount)==2
2934
+ && vBargraphChecked) {
2935
+ QAbstractSlider* sliderOrKnob =
2936
+ qobject_cast<QAbstractSlider*>(lastObject);
2937
+ // only if the previously found QObject is neither slider nor
2938
+ // knob
2939
+ if(!sliderOrKnob) {
2940
+ #if FAUSTQT_DEBUG>1
2941
+ qDebug("found horizontal bargraph with numerical style!");
2942
+ #endif
2943
+ num->setProperty("vstParam", vstParamCount);
2944
+ QList<QObject*> c; c.append(num);
2945
+ controls.append(c);
2946
+ passive_controls.append(num);
2947
+ control_values[vstParamCount] = effect->getMinimum(vstParamCount);
2948
+
2949
+ vstParamCount++;
2950
+ }
2951
+ }
2952
+ }
2953
+
2954
+ // CheckBox
2955
+ QCheckBox* checkBox = qobject_cast<QCheckBox*>(*i);
2956
+ if (checkBox) {
2957
+ #if FAUSTQT_DEBUG>1
2958
+ qDebug("found checkbox!");
2959
+ #endif
2960
+ checkBox->setProperty("vstParam", vstParamCount);
2961
+ QList<QObject*> c; c.append(checkBox);
2962
+ controls.append(c);
2963
+
2964
+ connect(checkBox, SIGNAL(stateChanged(int)), this,
2965
+ SLOT(updateVST_checkBox()), Qt::QueuedConnection);
2966
+
2967
+ // if the VST parameter of the checkbox is less than 0.5 then the
2968
+ // checkbox is unchecked
2969
+ updateQTGUI(checkBox, effect->getParameter(vstParamCount));
2970
+
2971
+ vstParamCount++;
2972
+ }
2973
+
2974
+ // Bargraph
2975
+ AbstractDisplay* bargraph = dynamic_cast<AbstractDisplay*>(*i);
2976
+ if (bargraph) {
2977
+ if(effect->isPassiveControl(vstParamCount)==1) {
2978
+ #if FAUSTQT_DEBUG>1
2979
+ qDebug("found vertical bargraph!");
2980
+ #endif
2981
+ vBargraphChecked = false;
2982
+ }
2983
+ #if FAUSTQT_DEBUG>1
2984
+ else
2985
+ qDebug("found horizontal bargraph!");
2986
+ #endif
2987
+
2988
+ bargraph->setProperty("vstParam", vstParamCount);
2989
+ //led->setProperty("elemType", "led");
2990
+ QList<QObject*> c; c.append(bargraph);
2991
+ controls.append(c);
2992
+ passive_controls.append(bargraph);
2993
+ control_values[vstParamCount] = effect->getMinimum(vstParamCount);
2994
+
2995
+ vstParamCount++;
2996
+ }
2997
+
2998
+ // Radiobuttons
2999
+ uiRadioButtons* uiRadio = dynamic_cast<uiRadioButtons*>(*i);
3000
+ if (uiRadio) {
3001
+ #if FAUSTQT_DEBUG>1
3002
+ qDebug("found radio buttons!");
3003
+ #endif
3004
+
3005
+ QList<QRadioButton*> radiobuttons =
3006
+ uiRadio->findChildren<QRadioButton*>();
3007
+
3008
+ int radioCount = 0;
3009
+ QList<QObject*> c;
3010
+ // iterate over all radio buttons in this group
3011
+ for (QList<QRadioButton*>::iterator r = radiobuttons.begin();
3012
+ r != radiobuttons.end(); ++r) {
3013
+ float minimum = effect->getMinimum(vstParamCount);
3014
+ float maximum = effect->getMaximum(vstParamCount);
3015
+ float step = effect->getStep(vstParamCount);
3016
+ // set all properties needed for updateVST()
3017
+ (*r)->setProperty("value", radioCount);
3018
+ (*r)->setProperty("vstParam", vstParamCount);
3019
+ (*r)->setProperty("minimum", minimum);
3020
+ (*r)->setProperty("maximum", maximum);
3021
+ (*r)->setProperty("singleStep", step);
3022
+ connect((*r), SIGNAL(clicked(bool)), this, SLOT(updateVST()),
3023
+ Qt::QueuedConnection);
3024
+
3025
+ // set the proper radio button as "clicked" when the GUI opens
3026
+ updateQTGUI(*r, effect->getParameter(vstParamCount));
3027
+ c.append(*r);
3028
+ radioCount++;
3029
+ }
3030
+ controls.append(c);
3031
+ vstParamCount++;
3032
+ }
3033
+
3034
+ // Menu
3035
+ uiMenu* menu = dynamic_cast<uiMenu*>(*i);
3036
+ if (menu) {
3037
+ #if FAUSTQT_DEBUG>1
3038
+ qDebug("found menu!");
3039
+ #endif
3040
+
3041
+ float minimum = effect->getMinimum(vstParamCount);
3042
+ float maximum = effect->getMaximum(vstParamCount);
3043
+ float step = effect->getStep(vstParamCount);
3044
+
3045
+ menu->setProperty("vstParam", vstParamCount);
3046
+ menu->setProperty("minimum", minimum);
3047
+ menu->setProperty("maximum", maximum);
3048
+ menu->setProperty("singleStep", step);
3049
+ QList<QObject*> c; c.append(menu);
3050
+ controls.append(c);
3051
+
3052
+ connect(menu, SIGNAL(activated(int)), this, SLOT(updateVST()),
3053
+ Qt::QueuedConnection);
3054
+
3055
+ updateQTGUI(menu, effect->getParameter(vstParamCount));
3056
+
3057
+ vstParamCount++;
3058
+ }
3059
+ // save the QObject of this iteration
3060
+ lastObject = (*i);
3061
+ }
3062
+
3063
+
3064
+ #if FAUSTQT_DEBUG>1
3065
+ qDebug() << "VST parameters assigned: " << vstParamCount;
3066
+ #endif
3067
+
3068
+ #ifdef HTTPCTRL
3069
+ httpdinterface->run();
3070
+ #ifdef QRCODECTRL
3071
+ // FIXME: This will pop up each time the GUI is opened. We should maybe have
3072
+ // a little button in the GUI somewhere so that the user can show the QR
3073
+ // code when needed.
3074
+ qtinterface->displayQRCode(httpdinterface->getTCPPort());
3075
+ #endif
3076
+ #endif
3077
+
3078
+ #ifdef OSCCTRL
3079
+ oscinterface->run();
3080
+ #endif
3081
+
3082
+ qtinterface->run();
3083
+
3084
+ // The STYLE symbol is set during compilation when using the -style option
3085
+ // of the faust2faustvst script or the corresponding options in the
3086
+ // Makefile. You can also set this manually if needed, but note that the
3087
+ // corresponding resource needs to be present in the qmake project (this is
3088
+ // taken care of automagically when using the -style option). Otherwise (or
3089
+ // if no style was specified) the default style will be used. -ag
3090
+ #ifdef STYLE
3091
+ // set the style sheet for this GUI, if any
3092
+ QString styleSheet("");
3093
+ // C preprocessor stringify magic to insert the style sheet name
3094
+ #define __xstr(s) __str(s)
3095
+ #define __str(s) #s
3096
+ QFile file(":/" __xstr(STYLE) ".qss");
3097
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
3098
+ styleSheet = QLatin1String(file.readAll());
3099
+ file.close();
3100
+ }
3101
+ widget->setStyleSheet(styleSheet);
3102
+ #endif
3103
+
3104
+ // embed the plug-in widget into the window provided by the host
3105
+ Display* display = QX11Info::display();
3106
+ XReparentWindow(display, widget->winId(), WId(ptr), 0, 0);
3107
+ XMapWindow(display, WId(ptr));
3108
+ XFlush(display);
3109
+
3110
+ widget->show();
3111
+
3112
+ #if FAUSTQT_DEBUG>1
3113
+ qDebug() << "Number of controls: " << controls.size();
3114
+ qDebug() << "Number of passive controls: " << passive_controls.size();
3115
+ #endif
3116
+
3117
+ uidsp = dsp;
3118
+ return true;
3119
+ }
3120
+
3121
+ /**
3122
+ * @brief VSTQtGUI::idle
3123
+ * - idle() is called repeatedly at some time interval determined by the host
3124
+ * to process any pending GUI events
3125
+ * - it also updates control elements in the GUI as needed
3126
+ */
3127
+ void VSTQtGUI::idle()
3128
+ {
3129
+ if (qApp) {
3130
+ QApplication::processEvents();
3131
+ for (int i = 0; i < controls.size(); ++i) {
3132
+ float val = effect->getParameter(i);
3133
+ if (!controls[i].empty() && control_values[i] != val) {
3134
+ if (effect->isPassiveControl(i)) {
3135
+ for (QList<QObject*>::iterator it = controls[i].begin();
3136
+ it != controls[i].end(); ++it)
3137
+ updatePassiveControl(*it, val);
3138
+ } else {
3139
+ for (QList<QObject*>::iterator it = controls[i].begin();
3140
+ it != controls[i].end(); ++it)
3141
+ updateQTGUI(*it, val, false);
3142
+ }
3143
+ control_values[i] = val;
3144
+ }
3145
+ }
3146
+ }
3147
+ #if FAUSTQT_DEBUG
3148
+ else
3149
+ qDebug("qApp ERROR! QApplication doesn't exist!");
3150
+ #endif
3151
+ }
3152
+
3153
+ /**
3154
+ * @brief VSTQtGUI::close
3155
+ * - when closing the plugin GUI, all GUI elements are destroyed and the
3156
+ * controls and passive_controls vectors are cleared
3157
+ */
3158
+ void VSTQtGUI::close()
3159
+ {
3160
+ #ifdef HTTPCTRL
3161
+ httpdinterface->stop();
3162
+ delete httpdinterface;
3163
+ httpdinterface = NULL;
3164
+ #endif
3165
+ #ifdef OSCCTRL
3166
+ oscinterface->stop();
3167
+ delete oscinterface;
3168
+ oscinterface = NULL;
3169
+ #endif
3170
+ qtinterface->stop();
3171
+ delete qtinterface;
3172
+ qtinterface = NULL;
3173
+ delete widget;
3174
+ widget = NULL;
3175
+ delete uidsp;
3176
+ uidsp = NULL;
3177
+ controls.clear();
3178
+ passive_controls.clear();
3179
+
3180
+ #if FAUSTQT_DEBUG
3181
+ qDebug("close editor");
3182
+ #endif
3183
+ AEffEditor::close();
3184
+ }
3185
+
3186
+ /**
3187
+ * @brief VSTQtGUI::getRect
3188
+ * - required pointer "rect" to determine the size of the plug-in window
3189
+ * @param rect
3190
+ * @return
3191
+ */
3192
+ bool VSTQtGUI::getRect (ERect** rect)
3193
+ {
3194
+ *rect = &rectangle;
3195
+ return true;
3196
+ }
3197
+
3198
+ /**
3199
+ * @brief VSTQtGUI::valueToVST
3200
+ * - converts a value from the Faust to the VST representation
3201
+ * @param value
3202
+ * @param minimum
3203
+ * @param maximum
3204
+ * @return
3205
+ */
3206
+ float VSTQtGUI::valueToVST(double value, double minimum,
3207
+ double maximum)
3208
+ {
3209
+ float newFloat = 0.f;
3210
+ if(minimum==maximum)
3211
+ return newFloat;
3212
+ else {
3213
+ newFloat = (value-minimum) / (maximum-minimum);
3214
+ return newFloat;
3215
+ }
3216
+ }
3217
+
3218
+ /**
3219
+ * @brief VSTQtGUI::updateQTGUI
3220
+ * - method to update a GUI element
3221
+ * - called for GUI elements in the open() and idle() methods
3222
+ * - VST values are converted to Faust ranges to determine the position of
3223
+ * sliders, knobs, etc.
3224
+ * @param object
3225
+ * @param value
3226
+ */
3227
+ void VSTQtGUI::updateQTGUI(QObject* object, float value, bool init)
3228
+ {
3229
+ const double eps = 1e-5;
3230
+ double minimum, maximum, step, newValue;
3231
+ char* valueChar;
3232
+
3233
+ if (init) {
3234
+ int vstParam = object->property("vstParam").toInt();
3235
+ control_values[vstParam] = value;
3236
+ }
3237
+
3238
+ // checkboxes and radio buttons need special treatment
3239
+ QCheckBox* checkBox = qobject_cast<QCheckBox*>(object);
3240
+ if (checkBox) {
3241
+ if (value < 0.5f)
3242
+ checkBox->setChecked(false);
3243
+ else
3244
+ checkBox->setChecked(true);
3245
+ return;
3246
+ }
3247
+
3248
+ minimum = object->property("minimum").toDouble();
3249
+ maximum = object->property("maximum").toDouble();
3250
+ step = object->property("singleStep").toDouble();
3251
+
3252
+ QRadioButton* radioBut = qobject_cast<QRadioButton*>(object);
3253
+ if (radioBut) {
3254
+ int radioVal = radioBut->property("value").toInt();
3255
+ float val = valueToVST(radioVal, minimum, maximum);
3256
+ if (fabs(val-value)/(1+fabs(maximum-minimum)) < eps)
3257
+ radioBut->click();
3258
+ return;
3259
+ }
3260
+
3261
+ if (QString(object->metaObject()->className())=="uiMenu")
3262
+ valueChar = "currentIndex";
3263
+ else
3264
+ valueChar = "value";
3265
+
3266
+ #if FAUSTQT_DEBUG>1
3267
+ int vstParam = object->property("vstParam").toInt();
3268
+ qDebug() << "QTGUI: vstParam: " << vstParam;
3269
+ qDebug() << "QTGUI: VST value: " << value;
3270
+ qDebug() << "QTGUI: old Qt value: "
3271
+ << object->property(valueChar).toDouble();
3272
+ #endif
3273
+
3274
+ newValue = (minimum==maximum)?minimum : minimum+quantize(value*
3275
+ (maximum-minimum), step);
3276
+
3277
+ if (fabs(newValue) < fabs(step) ||
3278
+ fabs(newValue)/fabs(maximum-minimum) < eps)
3279
+ newValue = 0.0;
3280
+
3281
+ // set new value with setProperty("value",..), as setValue() is not
3282
+ // defined for QObject
3283
+ object->setProperty(valueChar, newValue);
3284
+ #if FAUSTQT_DEBUG>1
3285
+ qDebug() << "QTGUI: new Qt value: "
3286
+ << object->property(valueChar).toDouble();
3287
+ #endif
3288
+ uiMenu* menu = dynamic_cast<uiMenu*>(object);
3289
+ if (menu) menu->updateZone(0); // updates the currentIndex
3290
+ }
3291
+
3292
+ /**
3293
+ * @brief VSTQtGUI::updatePassiveControl
3294
+ * - method to update the passive control elements (bargraphs)
3295
+ * - called in idle()
3296
+ * @param object
3297
+ */
3298
+ void VSTQtGUI::updatePassiveControl(QObject* object, float value)
3299
+ {
3300
+ int vstParam = object->property("vstParam").toInt();
3301
+ float minimum = effect->getMinimum(vstParam);
3302
+ float maximum = effect->getMaximum(vstParam);
3303
+
3304
+ // convert the VST value back to the corresponding Faust value
3305
+ float fValue = value*maximum - value*minimum + minimum;
3306
+
3307
+ AbstractDisplay* bargraph = dynamic_cast<AbstractDisplay*>(object);
3308
+ QDoubleSpinBox* numDisplay = dynamic_cast<QDoubleSpinBox*>(object);
3309
+
3310
+ if(bargraph)
3311
+ bargraph->setValue(fValue);
3312
+ else if(numDisplay)
3313
+ numDisplay->setValue(fValue);
3314
+ }
3315
+
3316
+ /***********************
3317
+ ******* Slots ********
3318
+ ***********************/
3319
+
3320
+ // The slots are called in response to interactive changes of a GUI element
3321
+ // (e.g., slider movements). Here we update the corresponding VST parameters.
3322
+
3323
+ /**
3324
+ * @brief VSTQtGUI::updateVST_buttonPressed
3325
+ * - slot for pressing a button object
3326
+ */
3327
+ void VSTQtGUI::updateVST_buttonPressed()
3328
+ {
3329
+ int vstParam = QObject::sender()->property("vstParam").toInt();
3330
+ #if FAUSTQT_DEBUG>1
3331
+ qDebug() << "VST: vstParam: " << vstParam;
3332
+ qDebug() << "VST: button pressed";
3333
+ #endif
3334
+ effect->setParameter(vstParam, 1.0f);
3335
+ control_values[vstParam] = 1.0f;
3336
+ }
3337
+
3338
+ /**
3339
+ * @brief VSTQtGUI::updateVST_buttonReleased
3340
+ * - slot for releasing a button object
3341
+ */
3342
+ void VSTQtGUI::updateVST_buttonReleased()
3343
+ {
3344
+ int vstParam = QObject::sender()->property("vstParam").toInt();
3345
+ #if FAUSTQT_DEBUG>1
3346
+ qDebug() << "VST: vstParam: " << vstParam;
3347
+ qDebug() << "VST: button released";
3348
+ #endif
3349
+ effect->setParameter(vstParam, 0.0f);
3350
+ control_values[vstParam] = 0.0f;
3351
+ }
3352
+
3353
+ /**
3354
+ * @brief VSTQtGUI::updateVST_checkBox
3355
+ * - slot for check boxes
3356
+ */
3357
+ void VSTQtGUI::updateVST_checkBox()
3358
+ {
3359
+ int vstParam = QObject::sender()->property("vstParam").toInt();
3360
+ #if FAUSTQT_DEBUG>1
3361
+ qDebug() << "VST: vstParam: " << vstParam;
3362
+ #endif
3363
+
3364
+ // if CheckBox == checked
3365
+ if(QObject::sender()->property("checked").toBool()) {
3366
+ #if FAUSTQT_DEBUG>1
3367
+ qDebug("checkbox checked");
3368
+ #endif
3369
+ effect->setParameter(vstParam, 1.0f);
3370
+ control_values[vstParam] = 1.0f;
3371
+ } else {
3372
+ #if FAUSTQT_DEBUG>1
3373
+ qDebug("checkbox unchecked");
3374
+ #endif
3375
+ effect->setParameter(vstParam, 0.0f);
3376
+ control_values[vstParam] = 0.0f;
3377
+ }
3378
+ }
3379
+
3380
+ /**
3381
+ * @brief VSTQtGUI::updateVST
3382
+ * - slot for all other active control elements (sliders, knobs, menus, radio
3383
+ * buttons etc.)
3384
+ */
3385
+ void VSTQtGUI::updateVST()
3386
+ {
3387
+ double value, minimum, maximum, step;
3388
+ int vstParam;
3389
+
3390
+ // for uiMenu we have the property "currentIndex" instead of the property
3391
+ // "value"
3392
+ if (QString(QObject::sender()->metaObject()->className())=="uiMenu")
3393
+ value = QObject::sender()->property("currentIndex").toDouble();
3394
+ else
3395
+ value = QObject::sender()->property("value").toDouble();
3396
+ vstParam = QObject::sender()->property("vstParam").toInt();
3397
+ minimum = QObject::sender()->property("minimum").toDouble();
3398
+ maximum = QObject::sender()->property("maximum").toDouble();
3399
+ step = QObject::sender()->property("singleStep").toDouble();
3400
+
3401
+ #if FAUSTQT_DEBUG>1
3402
+ qDebug() << "VST: vstParam: " << vstParam;
3403
+ char text[32];
3404
+ effect->getParameterName(vstParam, text);
3405
+ qDebug() << "VST: label: " << text;
3406
+ qDebug() << "VST: min: " << minimum;
3407
+ qDebug() << "VST: max: " << maximum;
3408
+ qDebug() << "VST: step: " << step;
3409
+ qDebug() << "VST: new Qt value: " << value;
3410
+ qDebug() << "VST: old VST value: " << effect->getParameter(vstParam);
3411
+ #endif
3412
+
3413
+ float newFloat = valueToVST(value, minimum, maximum);
3414
+ effect->setParameter(vstParam, newFloat);
3415
+ control_values[vstParam] = newFloat;
3416
+ #if FAUSTQT_DEBUG>1
3417
+ qDebug() << "VST: new VST value: " << effect->getParameter(vstParam);
3418
+ #endif
3419
+ #if VOICE_CTRLS
3420
+ if (vstParam >= effect->getNumControls()) {
3421
+ // Extra polyphony and tuning controls. Generate some informative tooltips
3422
+ // for these so that the user understands the meaning of these values.
3423
+ QWidget *widget = qobject_cast<QWidget*>(QObject::sender());
3424
+ char text[32];
3425
+ effect->getParameterDisplay(vstParam, text);
3426
+ widget->setToolTip(text);
3427
+ // Also make sure that we trigger a host GUI update for changes in the
3428
+ // tuning control here, since this isn't done elsewhere.
3429
+ if (vstParam > effect->getNumControls())
3430
+ effect->updateDisplay();
3431
+ }
3432
+ #endif
3433
+ }
3434
+
3435
+ #endif // FAUST_UI