├── .gitignore ├── Design.txt ├── Digits Manual.pdf ├── License.txt ├── README ├── graphics └── digits │ ├── CosNoiseRockerV.png │ ├── CosSinRockerV.png │ ├── DialHandle_LCD.png │ ├── Dial_LCD.png │ ├── DigitsBG.png │ ├── DigitsBG.xcf │ ├── HSliderBG.png │ ├── HSliderNub.png │ └── Logo.png ├── linux └── Digits.make ├── mac ├── Digits-Info.plist └── Main.xcodeproj │ ├── PDVST.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ ├── PDVST.xccheckout │ │ │ └── PDVST.xcscmblueprint │ │ └── xcuserdata │ │ │ └── louis.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ └── louis.xcuserdatad │ │ └── xcschemes │ │ ├── Digits.xcscheme │ │ ├── DigitsBench.xcscheme │ │ └── xcschememanagement.plist │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── Main.xcscmblueprint │ │ ├── PDVST.xccheckout │ │ └── PDVST.xcscmblueprint │ └── xcuserdata │ │ └── louis.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ └── louis.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── Digits.xcscheme │ └── xcschememanagement.plist ├── patches ├── Basses │ ├── 404.fxp │ ├── ChorusBass.fxp │ ├── ElBass II.fxp │ ├── ElBass.fxp │ ├── EyeEye.fxp │ ├── FMBass.fxp │ ├── FlangerBass.fxp │ ├── LazyBass.fxp │ ├── PWMBass.fxp │ ├── PhatterBass.fxp │ ├── RubberBand.fxp │ ├── Splatter.fxp │ ├── SquareBass.fxp │ ├── Sub Fuzz.fxp │ ├── Sub.fxp │ └── ThunkyBass.fxp ├── Chords │ ├── BrassEns.fxp │ ├── ElectricOrgan II.fxp │ ├── ElectricOrgan.fxp │ ├── FunKeyRiffs.fxp │ ├── Funkdafy II.fxp │ ├── Funkdafy.fxp │ ├── FuzzBox.fxp │ ├── HiToneChords.fxp │ ├── MusicBox.fxp │ ├── ToySynthPiano II.fxp │ └── ToySynthPiano.fxp ├── DemoBank │ ├── BrassySlicerLead.fxp │ ├── ChorusBass.fxp │ ├── EasternArpeg.fxp │ ├── ElBass.fxp │ ├── FutureTines.fxp │ ├── GhostChoir.fxp │ ├── InitTone.fxp │ ├── Jar.fxp │ ├── SIDLead.fxp │ ├── SeriousWhales.fxp │ ├── StringEns.fxp │ └── ThunkyBass.fxp ├── Leads │ ├── AttackPoly.fxp │ ├── BellLead.fxp │ ├── BrassLead.fxp │ ├── BrassLeadMellow.fxp │ ├── BrassySlicerLead.fxp │ ├── Chiff.fxp │ ├── FierceLead.fxp │ ├── FoggyCliff.fxp │ ├── FuzzyHoover.fxp │ ├── HardCorpLead.fxp │ ├── HarshLead.fxp │ ├── HollowTube.fxp │ ├── Hyperflute.fxp │ ├── Mystery.fxp │ ├── RavingLunatic.fxp │ ├── ResoLead.fxp │ ├── SIDLead II.fxp │ ├── SIDLead.fxp │ ├── SeriousWhales.fxp │ ├── SpaceOboe.fxp │ ├── SynReed.fxp │ └── ViolinLead.fxp ├── Pads │ ├── Atlantis.fxp │ ├── BellBrassPad.fxp │ ├── Choir II.fxp │ ├── DreamPad.fxp │ ├── FilteryChorusy.fxp │ ├── FilteryPads.fxp │ ├── FlangerStringEns.fxp │ ├── GhostChoir.fxp │ ├── Jar II.fxp │ ├── Jar.fxp │ ├── Planetary.fxp │ ├── StringEns.fxp │ ├── StringEnsBright.fxp │ ├── TheCreeps.fxp │ └── WinteryPad.fxp ├── Stabs │ ├── AlienChimes.fxp │ ├── Bells.fxp │ ├── Darius.fxp │ ├── EasternArpeg.fxp │ ├── FutureTines.fxp │ ├── Ghosts.fxp │ ├── HouseStabs.fxp │ ├── POW.fxp │ ├── Quack.fxp │ ├── Soft Mallet.fxp │ ├── ThunkyArp.fxp │ └── VelocityRubber.fxp └── Sweeps │ ├── FunnyBone.fxp │ ├── HiSweep-Overdrive.fxp │ ├── HiSweep.fxp │ ├── HowlingTubeSweep.fxp │ ├── MeanSweeps.fxp │ ├── Riser I.fxp │ ├── Riser II.fxp │ ├── Riser III.fxp │ ├── Riser IV.fxp │ ├── SeriousPad.fxp │ ├── TubularBellSweep.fxp │ ├── VisciousFM 2.fxp │ ├── VisciousFM.fxp │ ├── Whoosh.fxp │ └── WobblySweep.fxp ├── src ├── components │ ├── BufferManager.cpp │ ├── BufferManager.h │ ├── Chorus.cpp │ ├── Chorus.h │ ├── Compressor.cpp │ ├── Compressor.h │ ├── Contour.cpp │ ├── Contour.h │ ├── FauxVst.h │ ├── FilterBank.h │ ├── LFO.h │ ├── LGDebug.h │ ├── NoiseGen.cpp │ ├── NoiseGen.h │ ├── Oversampler.cpp │ ├── Oversampler.h │ ├── PatchBankList.h │ ├── PatchBankListMac.cpp │ ├── PatchBankListMac.h │ ├── PatchBankListWin.cpp │ ├── PatchBankListWin.h │ ├── SndBuf.cpp │ ├── SndBuf.h │ ├── Tables.cpp │ ├── Tables.h │ ├── Voice.cpp │ └── Voice.h └── digits │ ├── DigitsBench.cpp │ ├── EditorWindow.cpp │ ├── EditorWindow.h │ ├── Patches.cpp │ ├── Patches.h │ ├── PhaseDist.cpp │ ├── PhaseDist.h │ ├── ResoGen.cpp │ ├── ResoGen.h │ ├── VstCore.cpp │ └── VstCore.h └── windows ├── Digits.rc ├── DigitsVST.vcxproj ├── Main.VC.opendb ├── Main.sln └── vstplug.def /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /Design.txt: -------------------------------------------------------------------------------- 1 | Hi! Since I've opened up the source for Digits, I wanted to take a second to 2 | talk about some of the design decisions I made while writing it. 3 | 4 | If you didn't know, Digits started out as a simple project for me to work on 5 | while I was hanging out at hacker spaces. It started pretty modestly. The 6 | first version only sported one LFO, only had the delay effect, no filters, 7 | and the envelopes were trapezoidal. It has come a long way! 8 | 9 | One thing I was particularly happy with was how the phase distortion algorithm 10 | came out. While some examples I've seen use different routines for different 11 | waveshapes, Digits uses a consistent formula and just changes settings to 12 | produce all of its waveforms. For example, saw means you run the shaper 13 | once per cycle. Square means you run the shaper twice per cycle. Skew means 14 | that you alter position of the node where the knee in the phase distortion is. 15 | The pulse-width modulation is faked in by applying a second shaper to the 16 | entire generator (so, a shaper within a shaper). This is also why the 17 | pulse-width modulation causes the waveform to brighten as the pulse narrows. 18 | 19 | The design of Digits is not without some regrets: I went with a control rate 20 | for the main audio loop instead of making it 100% sample-accurate. This is 21 | because that's how I always did synthesizers, and this is how a lot of older 22 | synths operated. It makes for a messy loop and causes a tiny amount of jitter. 23 | A much better way of doing it would be to render the number of samples between 24 | MIDI events precisely. 25 | 26 | A big problem in the user interface is the Shaper Lock in the filter section. 27 | It provides a lot of flexibility, but at the cost of being unorthodox and 28 | confusing to many users. 29 | 30 | My final regret that I want to talk about is how much of a mess the UI code 31 | is! It really grew a lot. If I did it again, I'd leverage classes more to 32 | clean it up. This ended up looking more the way it'd look if you just wrote 33 | it in flat C. Oops. 34 | 35 | Optimization: While the oscillators look like they are doing a lot of heavy 36 | lifting, they are actually fairly fast. However, the LFOs and especially the 37 | envelopes are slow. I would suggest making a table-driven envelope to replace 38 | it. Be aware though that the attack is an inverse curve from the decay shape. 39 | 40 | You might also notice that the oscillator uses an uninterpolated lookup. I 41 | investigated on a few devices, seeing whether the increased table size might 42 | cause a CPU cache miss, or whether it would drastically hurt the sound 43 | quality. It was very fast without interpolation and did not appear to hurt 44 | the sound quality too much, so that is what I went for. My secret shame. 45 | 46 | Lastly, there are many, many areas where you could improve the speed with 47 | vector processing. However, this particular version of the Digits engine only 48 | uses basic C++ code and no inline assembly or vector intrinsics. 49 | 50 | As far as sound quality goes, it can alias a little bit at 44 or 48khz. I 51 | started on an oversampling routine but never fit it into the code (this is 52 | all done as an after-work hobby after all). Though aliasing is combated a bit 53 | by toning down the shaper at higher pitches, a little oversampling might 54 | go a long way. 55 | 56 | Anyway, that's about it! Happy hacking; be sure to read the License.txt! 57 | (Digits is licensed under GPL) 58 | 59 | Cheers, 60 | Louis "Extent of the Jam" Gorenfeld 61 | louis.gorenfeld@gmail.com 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Digits Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/Digits Manual.pdf -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | # Digits VST 2 | 3 | http://www.extentofthejam.com/ 4 | 5 | ## license 6 | 7 | Please read License.txt! :) Digits is licensed under the GPL. 8 | 9 | ## building 10 | 11 | ### prerequisites 12 | 13 | You'll need the Steinberg VST SDK downloaded into the sdks/vstsdk2.4 directory. 14 | 15 | ### linux 16 | 17 | cd linux 18 | make -f Digits.make 19 | -------------------------------------------------------------------------------- /graphics/digits/CosNoiseRockerV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/CosNoiseRockerV.png -------------------------------------------------------------------------------- /graphics/digits/CosSinRockerV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/CosSinRockerV.png -------------------------------------------------------------------------------- /graphics/digits/DialHandle_LCD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/DialHandle_LCD.png -------------------------------------------------------------------------------- /graphics/digits/Dial_LCD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/Dial_LCD.png -------------------------------------------------------------------------------- /graphics/digits/DigitsBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/DigitsBG.png -------------------------------------------------------------------------------- /graphics/digits/DigitsBG.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/DigitsBG.xcf -------------------------------------------------------------------------------- /graphics/digits/HSliderBG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/HSliderBG.png -------------------------------------------------------------------------------- /graphics/digits/HSliderNub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/HSliderNub.png -------------------------------------------------------------------------------- /graphics/digits/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/graphics/digits/Logo.png -------------------------------------------------------------------------------- /linux/Digits.make: -------------------------------------------------------------------------------- 1 | TARGET = DigitsVST.so 2 | 3 | CPP = g++ 4 | CXXFLAGS = -Wall -O3 -D__cdecl="" -I../sdks/vstsdk2.4 -fvisibility=hidden -DNO_EDITOR -DDIGITS_PRO -I../src/digits -I../src/components -fPIC 5 | 6 | CSOURCES = ../src/components/BufferManager.cpp \ 7 | ../src/components/Chorus.cpp ../src/components/Contour.cpp ../src/digits/PhaseDist.cpp ../src/digits/ResoGen.cpp ../src/components/SndBuf.cpp ../src/components/Tables.cpp ../src/components/Voice.cpp ../src/digits/VstCore.cpp ../sdks/vstsdk2.4/public.sdk/source/vst2.x/vstplugmain.cpp 8 | OBJS = $(CSOURCES:.cpp=.o) 9 | ALLOBJ = $(OBJS) $(VSTSDKDIR)/public.sdk/source/vst2.x/audioeffect.o $(VSTSDKDIR)/public.sdk/source/vst2.x/audioeffectx.o 10 | SRCDIR = ../src 11 | VSTSDKDIR = ../sdks/vstsdk2.4 12 | 13 | ${TARGET} : $(ALLOBJ) 14 | $(CPP) -fPIC -DPIC -shared ${CXXFLAGS} -o ${TARGET} ${ALLOBJ} 15 | strip ${TARGET} 16 | 17 | %.o : $(SRCDIR)/%.cpp 18 | $(CPP) -c $< -o $@ $(CXXFLAGS) 19 | 20 | #.c.o : 21 | # ${CC} ${CC_FLAGS} -c $< 22 | 23 | #.cpp.o: 24 | # ${CC} ${CC_FLAGS} -c $< 25 | 26 | clean : 27 | rm -f ${TARGET} 28 | rm -f ${ALLOBJ} 29 | rm -f *~ 30 | rm -f source/*~ 31 | 32 | 33 | -------------------------------------------------------------------------------- /mac/Digits-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14F27 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | Digits 11 | CFBundleIdentifier 12 | com.extentofthejam.Digits 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | Digits 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 2.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleSupportedPlatforms 24 | 25 | MacOSX 26 | 27 | CFBundleVersion 28 | 2 29 | CFPlugInDynamicRegisterFunction 30 | 31 | CFPlugInDynamicRegistration 32 | 33 | CFPlugInFactories 34 | 35 | 00000000-0000-0000-0000-000000000000 36 | MyFactoryFunction 37 | 38 | CFPlugInTypes 39 | 40 | 00000000-0000-0000-0000-000000000000 41 | 42 | 00000000-0000-0000-0000-000000000000 43 | 44 | 45 | CFPlugInUnloadFunction 46 | 47 | DTCompiler 48 | com.apple.compilers.llvm.clang.1_0 49 | DTPlatformBuild 50 | 7C1002 51 | DTPlatformVersion 52 | GM 53 | DTSDKBuild 54 | 15C43 55 | DTSDKName 56 | macosx10.11 57 | DTXcode 58 | 0721 59 | DTXcodeBuild 60 | 7C1002 61 | 62 | 63 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/project.xcworkspace/xcshareddata/PDVST.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 389F805C-D228-474D-882B-A7E8333636C1 9 | IDESourceControlProjectName 10 | PDVST 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 14 | https://vstgui.svn.sourceforge.net/svnroot/vstgui/trunk/vstgui 15 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 16 | http://www.extentofthejam.com/DigitsVst/trunk 17 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 18 | http://www.extentofthejam.com/DigitsVst/vstsdk2.4 19 | 20 | IDESourceControlProjectPath 21 | Mac/PDVST.xcodeproj/project.xcworkspace 22 | IDESourceControlProjectRelativeInstallPathDictionary 23 | 24 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 25 | ../../../vstgui 26 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 27 | ../../.. 28 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 29 | ../../../vstsdk2.4 30 | 31 | IDESourceControlProjectRepositoryRootDictionary 32 | 33 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 34 | https://vstgui.svn.sourceforge.net/svnroot/vstgui 35 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 36 | http://www.extentofthejam.com/DigitsVst 37 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 38 | http://www.extentofthejam.com/DigitsVst 39 | 40 | IDESourceControlProjectURL 41 | http://www.extentofthejam.com/DigitsVst/trunk/Mac/PDVST.xcodeproj 42 | IDESourceControlProjectVersion 43 | 110 44 | IDESourceControlProjectWCCIdentifier 45 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 46 | IDESourceControlProjectWCConfigurations 47 | 48 | 49 | IDESourceControlRepositoryExtensionIdentifierKey 50 | public.vcs.subversion 51 | IDESourceControlRepositoryTrunkRelativeLocationKey 52 | trunk 53 | IDESourceControlWCCIdentifierKey 54 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 55 | IDESourceControlWCCName 56 | trunk 57 | 58 | 59 | IDESourceControlRepositoryExtensionIdentifierKey 60 | public.vcs.subversion 61 | IDESourceControlWCCIdentifierKey 62 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 63 | IDESourceControlWCCName 64 | vstgui 65 | 66 | 67 | IDESourceControlRepositoryExtensionIdentifierKey 68 | public.vcs.subversion 69 | IDESourceControlWCCIdentifierKey 70 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 71 | IDESourceControlWCCName 72 | vstsdk2 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/project.xcworkspace/xcshareddata/PDVST.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" : { 5 | 6 | } 7 | }, 8 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 9 | "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" : 0 10 | }, 11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "389F805C-D228-474D-882B-A7E8333636C1", 12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 13 | "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" : "DigitsVst\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "PDVST", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "trunk\/Mac\/PDVST.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "http:\/\/www.extentofthejam.com\/DigitsVst", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Subversion", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/project.xcworkspace/xcuserdata/louis.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/mac/Main.xcodeproj/PDVST.xcodeproj/project.xcworkspace/xcuserdata/louis.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/project.xcworkspace/xcuserdata/louis.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/xcuserdata/louis.xcuserdatad/xcschemes/Digits.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/xcuserdata/louis.xcuserdatad/xcschemes/DigitsBench.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/PDVST.xcodeproj/xcuserdata/louis.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Digits.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | DigitsBench.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 8D57630D048677EA00EA77CD 21 | 22 | primary 23 | 24 | 25 | BF8D1650160C075D002BAEBC 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/project.xcworkspace/xcshareddata/Main.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "fda82bb9-77cd-40e1-9680-d2fdca61505c", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | "fda82bb9-77cd-40e1-9680-d2fdca61505c" : { 5 | 6 | } 7 | }, 8 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 9 | "fda82bb9-77cd-40e1-9680-d2fdca61505c" : 9223372036854775807 10 | }, 11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "031BA8E8-F7BC-4D4E-90F7-0551FC4BDB0C", 12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 13 | "fda82bb9-77cd-40e1-9680-d2fdca61505c" : "eojsource\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "Main", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "trunk\/mac\/Main.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "http:\/\/www.extentofthejam.com\/eojsource", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Subversion", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "fda82bb9-77cd-40e1-9680-d2fdca61505c" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /mac/Main.xcodeproj/project.xcworkspace/xcshareddata/PDVST.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 389F805C-D228-474D-882B-A7E8333636C1 9 | IDESourceControlProjectName 10 | PDVST 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 14 | https://vstgui.svn.sourceforge.net/svnroot/vstgui/trunk/vstgui 15 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 16 | http://www.extentofthejam.com/DigitsVst/trunk 17 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 18 | http://www.extentofthejam.com/DigitsVst/vstsdk2.4 19 | 20 | IDESourceControlProjectPath 21 | Mac/PDVST.xcodeproj/project.xcworkspace 22 | IDESourceControlProjectRelativeInstallPathDictionary 23 | 24 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 25 | ../../../vstgui 26 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 27 | ../../.. 28 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 29 | ../../../vstsdk2.4 30 | 31 | IDESourceControlProjectRepositoryRootDictionary 32 | 33 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 34 | https://vstgui.svn.sourceforge.net/svnroot/vstgui 35 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 36 | http://www.extentofthejam.com/DigitsVst 37 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 38 | http://www.extentofthejam.com/DigitsVst 39 | 40 | IDESourceControlProjectURL 41 | http://www.extentofthejam.com/DigitsVst/trunk/Mac/PDVST.xcodeproj 42 | IDESourceControlProjectVersion 43 | 110 44 | IDESourceControlProjectWCCIdentifier 45 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 46 | IDESourceControlProjectWCConfigurations 47 | 48 | 49 | IDESourceControlRepositoryExtensionIdentifierKey 50 | public.vcs.subversion 51 | IDESourceControlRepositoryTrunkRelativeLocationKey 52 | trunk 53 | IDESourceControlWCCIdentifierKey 54 | 3BE785E0-25D8-46D7-9C6D-695762A0F67B 55 | IDESourceControlWCCName 56 | trunk 57 | 58 | 59 | IDESourceControlRepositoryExtensionIdentifierKey 60 | public.vcs.subversion 61 | IDESourceControlWCCIdentifierKey 62 | 17D9919C-DA53-4281-A0CD-C53F8CBB0AA6 63 | IDESourceControlWCCName 64 | vstgui 65 | 66 | 67 | IDESourceControlRepositoryExtensionIdentifierKey 68 | public.vcs.subversion 69 | IDESourceControlWCCIdentifierKey 70 | 7F7CAD0D-C3BE-4BD1-8868-99E4543B06BB 71 | IDESourceControlWCCName 72 | vstsdk2 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/project.xcworkspace/xcshareddata/PDVST.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" : { 5 | 6 | } 7 | }, 8 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 9 | "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" : 0 10 | }, 11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "389F805C-D228-474D-882B-A7E8333636C1", 12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 13 | "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" : "DigitsVst\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "PDVST", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "trunk\/Mac\/PDVST.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "http:\/\/www.extentofthejam.com\/DigitsVst", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Subversion", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "3d0f6ae8-fa23-4685-9a80-cfccffeb77e4" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /mac/Main.xcodeproj/project.xcworkspace/xcuserdata/louis.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/mac/Main.xcodeproj/project.xcworkspace/xcuserdata/louis.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /mac/Main.xcodeproj/project.xcworkspace/xcuserdata/louis.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/xcuserdata/louis.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/xcuserdata/louis.xcuserdatad/xcschemes/Digits.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /mac/Main.xcodeproj/xcuserdata/louis.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Digits.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8D57630D048677EA00EA77CD 16 | 17 | primary 18 | 19 | 20 | BF82490F1DC050C50073E18C 21 | 22 | primary 23 | 24 | 25 | BF8D1650160C075D002BAEBC 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /patches/Basses/404.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/404.fxp -------------------------------------------------------------------------------- /patches/Basses/ChorusBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/ChorusBass.fxp -------------------------------------------------------------------------------- /patches/Basses/ElBass II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/ElBass II.fxp -------------------------------------------------------------------------------- /patches/Basses/ElBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/ElBass.fxp -------------------------------------------------------------------------------- /patches/Basses/EyeEye.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/EyeEye.fxp -------------------------------------------------------------------------------- /patches/Basses/FMBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/FMBass.fxp -------------------------------------------------------------------------------- /patches/Basses/FlangerBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/FlangerBass.fxp -------------------------------------------------------------------------------- /patches/Basses/LazyBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/LazyBass.fxp -------------------------------------------------------------------------------- /patches/Basses/PWMBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/PWMBass.fxp -------------------------------------------------------------------------------- /patches/Basses/PhatterBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/PhatterBass.fxp -------------------------------------------------------------------------------- /patches/Basses/RubberBand.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/RubberBand.fxp -------------------------------------------------------------------------------- /patches/Basses/Splatter.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/Splatter.fxp -------------------------------------------------------------------------------- /patches/Basses/SquareBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/SquareBass.fxp -------------------------------------------------------------------------------- /patches/Basses/Sub Fuzz.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/Sub Fuzz.fxp -------------------------------------------------------------------------------- /patches/Basses/Sub.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/Sub.fxp -------------------------------------------------------------------------------- /patches/Basses/ThunkyBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Basses/ThunkyBass.fxp -------------------------------------------------------------------------------- /patches/Chords/BrassEns.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/BrassEns.fxp -------------------------------------------------------------------------------- /patches/Chords/ElectricOrgan II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/ElectricOrgan II.fxp -------------------------------------------------------------------------------- /patches/Chords/ElectricOrgan.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/ElectricOrgan.fxp -------------------------------------------------------------------------------- /patches/Chords/FunKeyRiffs.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/FunKeyRiffs.fxp -------------------------------------------------------------------------------- /patches/Chords/Funkdafy II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/Funkdafy II.fxp -------------------------------------------------------------------------------- /patches/Chords/Funkdafy.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/Funkdafy.fxp -------------------------------------------------------------------------------- /patches/Chords/FuzzBox.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/FuzzBox.fxp -------------------------------------------------------------------------------- /patches/Chords/HiToneChords.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/HiToneChords.fxp -------------------------------------------------------------------------------- /patches/Chords/MusicBox.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/MusicBox.fxp -------------------------------------------------------------------------------- /patches/Chords/ToySynthPiano II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/ToySynthPiano II.fxp -------------------------------------------------------------------------------- /patches/Chords/ToySynthPiano.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Chords/ToySynthPiano.fxp -------------------------------------------------------------------------------- /patches/DemoBank/BrassySlicerLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/BrassySlicerLead.fxp -------------------------------------------------------------------------------- /patches/DemoBank/ChorusBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/ChorusBass.fxp -------------------------------------------------------------------------------- /patches/DemoBank/EasternArpeg.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/EasternArpeg.fxp -------------------------------------------------------------------------------- /patches/DemoBank/ElBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/ElBass.fxp -------------------------------------------------------------------------------- /patches/DemoBank/FutureTines.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/FutureTines.fxp -------------------------------------------------------------------------------- /patches/DemoBank/GhostChoir.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/GhostChoir.fxp -------------------------------------------------------------------------------- /patches/DemoBank/InitTone.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/InitTone.fxp -------------------------------------------------------------------------------- /patches/DemoBank/Jar.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/Jar.fxp -------------------------------------------------------------------------------- /patches/DemoBank/SIDLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/SIDLead.fxp -------------------------------------------------------------------------------- /patches/DemoBank/SeriousWhales.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/SeriousWhales.fxp -------------------------------------------------------------------------------- /patches/DemoBank/StringEns.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/StringEns.fxp -------------------------------------------------------------------------------- /patches/DemoBank/ThunkyBass.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/DemoBank/ThunkyBass.fxp -------------------------------------------------------------------------------- /patches/Leads/AttackPoly.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/AttackPoly.fxp -------------------------------------------------------------------------------- /patches/Leads/BellLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/BellLead.fxp -------------------------------------------------------------------------------- /patches/Leads/BrassLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/BrassLead.fxp -------------------------------------------------------------------------------- /patches/Leads/BrassLeadMellow.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/BrassLeadMellow.fxp -------------------------------------------------------------------------------- /patches/Leads/BrassySlicerLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/BrassySlicerLead.fxp -------------------------------------------------------------------------------- /patches/Leads/Chiff.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/Chiff.fxp -------------------------------------------------------------------------------- /patches/Leads/FierceLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/FierceLead.fxp -------------------------------------------------------------------------------- /patches/Leads/FoggyCliff.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/FoggyCliff.fxp -------------------------------------------------------------------------------- /patches/Leads/FuzzyHoover.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/FuzzyHoover.fxp -------------------------------------------------------------------------------- /patches/Leads/HardCorpLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/HardCorpLead.fxp -------------------------------------------------------------------------------- /patches/Leads/HarshLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/HarshLead.fxp -------------------------------------------------------------------------------- /patches/Leads/HollowTube.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/HollowTube.fxp -------------------------------------------------------------------------------- /patches/Leads/Hyperflute.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/Hyperflute.fxp -------------------------------------------------------------------------------- /patches/Leads/Mystery.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/Mystery.fxp -------------------------------------------------------------------------------- /patches/Leads/RavingLunatic.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/RavingLunatic.fxp -------------------------------------------------------------------------------- /patches/Leads/ResoLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/ResoLead.fxp -------------------------------------------------------------------------------- /patches/Leads/SIDLead II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/SIDLead II.fxp -------------------------------------------------------------------------------- /patches/Leads/SIDLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/SIDLead.fxp -------------------------------------------------------------------------------- /patches/Leads/SeriousWhales.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/SeriousWhales.fxp -------------------------------------------------------------------------------- /patches/Leads/SpaceOboe.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/SpaceOboe.fxp -------------------------------------------------------------------------------- /patches/Leads/SynReed.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/SynReed.fxp -------------------------------------------------------------------------------- /patches/Leads/ViolinLead.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Leads/ViolinLead.fxp -------------------------------------------------------------------------------- /patches/Pads/Atlantis.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/Atlantis.fxp -------------------------------------------------------------------------------- /patches/Pads/BellBrassPad.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/BellBrassPad.fxp -------------------------------------------------------------------------------- /patches/Pads/Choir II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/Choir II.fxp -------------------------------------------------------------------------------- /patches/Pads/DreamPad.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/DreamPad.fxp -------------------------------------------------------------------------------- /patches/Pads/FilteryChorusy.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/FilteryChorusy.fxp -------------------------------------------------------------------------------- /patches/Pads/FilteryPads.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/FilteryPads.fxp -------------------------------------------------------------------------------- /patches/Pads/FlangerStringEns.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/FlangerStringEns.fxp -------------------------------------------------------------------------------- /patches/Pads/GhostChoir.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/GhostChoir.fxp -------------------------------------------------------------------------------- /patches/Pads/Jar II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/Jar II.fxp -------------------------------------------------------------------------------- /patches/Pads/Jar.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/Jar.fxp -------------------------------------------------------------------------------- /patches/Pads/Planetary.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/Planetary.fxp -------------------------------------------------------------------------------- /patches/Pads/StringEns.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/StringEns.fxp -------------------------------------------------------------------------------- /patches/Pads/StringEnsBright.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/StringEnsBright.fxp -------------------------------------------------------------------------------- /patches/Pads/TheCreeps.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/TheCreeps.fxp -------------------------------------------------------------------------------- /patches/Pads/WinteryPad.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Pads/WinteryPad.fxp -------------------------------------------------------------------------------- /patches/Stabs/AlienChimes.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/AlienChimes.fxp -------------------------------------------------------------------------------- /patches/Stabs/Bells.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/Bells.fxp -------------------------------------------------------------------------------- /patches/Stabs/Darius.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/Darius.fxp -------------------------------------------------------------------------------- /patches/Stabs/EasternArpeg.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/EasternArpeg.fxp -------------------------------------------------------------------------------- /patches/Stabs/FutureTines.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/FutureTines.fxp -------------------------------------------------------------------------------- /patches/Stabs/Ghosts.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/Ghosts.fxp -------------------------------------------------------------------------------- /patches/Stabs/HouseStabs.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/HouseStabs.fxp -------------------------------------------------------------------------------- /patches/Stabs/POW.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/POW.fxp -------------------------------------------------------------------------------- /patches/Stabs/Quack.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/Quack.fxp -------------------------------------------------------------------------------- /patches/Stabs/Soft Mallet.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/Soft Mallet.fxp -------------------------------------------------------------------------------- /patches/Stabs/ThunkyArp.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/ThunkyArp.fxp -------------------------------------------------------------------------------- /patches/Stabs/VelocityRubber.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Stabs/VelocityRubber.fxp -------------------------------------------------------------------------------- /patches/Sweeps/FunnyBone.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/FunnyBone.fxp -------------------------------------------------------------------------------- /patches/Sweeps/HiSweep-Overdrive.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/HiSweep-Overdrive.fxp -------------------------------------------------------------------------------- /patches/Sweeps/HiSweep.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/HiSweep.fxp -------------------------------------------------------------------------------- /patches/Sweeps/HowlingTubeSweep.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/HowlingTubeSweep.fxp -------------------------------------------------------------------------------- /patches/Sweeps/MeanSweeps.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/MeanSweeps.fxp -------------------------------------------------------------------------------- /patches/Sweeps/Riser I.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/Riser I.fxp -------------------------------------------------------------------------------- /patches/Sweeps/Riser II.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/Riser II.fxp -------------------------------------------------------------------------------- /patches/Sweeps/Riser III.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/Riser III.fxp -------------------------------------------------------------------------------- /patches/Sweeps/Riser IV.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/Riser IV.fxp -------------------------------------------------------------------------------- /patches/Sweeps/SeriousPad.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/SeriousPad.fxp -------------------------------------------------------------------------------- /patches/Sweeps/TubularBellSweep.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/TubularBellSweep.fxp -------------------------------------------------------------------------------- /patches/Sweeps/VisciousFM 2.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/VisciousFM 2.fxp -------------------------------------------------------------------------------- /patches/Sweeps/VisciousFM.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/VisciousFM.fxp -------------------------------------------------------------------------------- /patches/Sweeps/Whoosh.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/Whoosh.fxp -------------------------------------------------------------------------------- /patches/Sweeps/WobblySweep.fxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LouisGorenfeld/DigitsVst/f5ee4aa74e40b118bddcb3ef18d44b734e6fbef8/patches/Sweeps/WobblySweep.fxp -------------------------------------------------------------------------------- /src/components/BufferManager.cpp: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #include 4 | #include "BufferManager.h" 5 | #include 6 | 7 | void BufferManager::SetSamplingRate(float rate) 8 | { 9 | m_samplingRate = rate; 10 | m_ctlSize = rate; 11 | } 12 | 13 | void BufferManager::SetHostBlockSize(float blkSize) 14 | { 15 | m_blkSize = blkSize; 16 | 17 | if (m_bufList.empty()) 18 | return; 19 | 20 | // Resize all the buffers so that they match the 21 | // block size 22 | for (bufList_t::iterator it = m_bufList.begin(); 23 | it != m_bufList.end(); 24 | ++it) 25 | { 26 | if (*it) 27 | (*it)->Resize(m_blkSize); 28 | } 29 | printf("Block size %f\n", blkSize); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/components/BufferManager.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #ifndef _BUFFER_MANAGER_H_ 4 | #define _BUFFER_MANAGER_H_ 5 | 6 | #include 7 | #include "SndBuf.h" 8 | 9 | /* The SndBuf class is responsible for allocating and deallocating its 10 | * buffer, but the BufferManager class will automatically resize every 11 | * buffer when the block size changes in the host */ 12 | 13 | class BufferManager 14 | { 15 | public: 16 | BufferManager() { /* Safe defaults for out-of-order init */ SetSamplingRate(96000); } 17 | ~BufferManager() {} 18 | 19 | void AddBuffer(SndBuf *buf) { m_bufList.push_back(buf); } 20 | void RemoveBuffer(SndBuf *buf) { m_bufList.remove(buf); } 21 | 22 | float GetSamplingRate() { return m_samplingRate; } 23 | float GetControlSize() { return m_ctlSize; } 24 | static float GetControlRate() { return kCtlRate; } 25 | float GetHostBlockSize() { return m_blkSize; } 26 | 27 | void SetSamplingRate(float rate); 28 | void SetHostBlockSize(float blkSize); 29 | 30 | private: 31 | float m_samplingRate; 32 | float m_ctlSize; 33 | float m_blkSize; 34 | 35 | // Control rate in hz 36 | // TODO: This can be low, but we need to generate envelope signals 37 | static const float kCtlRate; 38 | 39 | // Buffers are managed by static routines so that they can 40 | // all be resized easily 41 | typedef std::list bufList_t; 42 | bufList_t m_bufList; 43 | }; 44 | 45 | #endif -------------------------------------------------------------------------------- /src/components/Chorus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // rand 3 | #include "Chorus.h" 4 | 5 | Chorus::Chorus() : 6 | m_delBuf(0), 7 | m_wIndex(0), 8 | m_lfoPos(0), 9 | m_lfoDelta(0), 10 | m_lfoRate(0), 11 | m_minDelay(0), 12 | m_range(0), 13 | m_minDelaySamp(0), 14 | m_rangeSamp(0), 15 | m_lastOut(0), 16 | m_feedback(0), 17 | m_sR(0), 18 | m_wet(0), 19 | m_bufSize(0), 20 | m_bins(512), 21 | m_shLast(0), 22 | m_shPos(0), 23 | m_noiseAmt(1.0f/256.0f) 24 | { 25 | m_preLP[0].SetFrequency(6000); 26 | m_preLP[1].SetFrequency(6000); 27 | m_postLP[0].SetFrequency(4000); 28 | m_postLP[1].SetFrequency(4000); 29 | m_postHP.SetFrequency(500); 30 | m_triSmoother.SetFrequency(5); 31 | SetSamplingRate(44100); // Just so that m_delBuf gets initialized 32 | } 33 | 34 | Chorus::~Chorus() 35 | { 36 | } 37 | 38 | void Chorus::SetSamplingRate(float sR) 39 | { 40 | m_sR = sR; 41 | if (m_delBuf) 42 | delete[] m_delBuf; 43 | m_delBuf = new float[(int)sR+1]; 44 | for (int i=0; i < sR+1; i++) 45 | m_delBuf[i] = 0; 46 | m_bufSize = sR; 47 | m_preLP[0].SetSamplingRate(sR); 48 | m_preLP[1].SetSamplingRate(sR); 49 | m_postLP[0].SetSamplingRate(sR); 50 | m_postLP[1].SetSamplingRate(sR); 51 | m_postHP.SetSamplingRate(sR); 52 | m_triSmoother.SetSamplingRate(sR); 53 | m_wIndex = 0; 54 | m_lfoPos = 0; 55 | m_shPos = 0; 56 | } 57 | 58 | void Chorus::RenderWet(float *in, float *out, int len) 59 | { 60 | // for (int i=0; i < len; i++) 61 | // in[i] = ((rand()&65536)/32767.0) - 1.0; 62 | // TODO: This could be made a lot more efficient 63 | 64 | m_preLP[0].Render(in, len); 65 | m_preLP[1].Render(in, len); 66 | 67 | for (int i=0; i= 1.0f) 72 | m_lfoPos -= 1.0f; 73 | 74 | if (m_lfoPos >= .5f) 75 | lfoSam = 2.0f - (m_lfoPos*2.0f); 76 | else 77 | lfoSam = m_lfoPos * 2.0f; 78 | lfoSam = m_triSmoother.Tick(lfoSam); 79 | 80 | float delay = m_minDelaySamp + (lfoSam*m_rangeSamp); 81 | float rIndex = (float)m_wIndex - delay; 82 | while (rIndex < 0) 83 | rIndex += m_bufSize; 84 | 85 | // fprintf(stderr, "delay=%d rIndex=%d, wIndex=%d\n", (int)delay, (int)rIndex, (int)m_wIndex); 86 | 87 | float rIndexFrac = fmod(rIndex, 1.0f); 88 | int rIndexInt = (int)rIndex; 89 | int rIndexInt2 = (int)rIndex - 1; 90 | while (rIndexInt2 < 0) 91 | rIndexInt2 += m_bufSize; 92 | 93 | // Sample hold to emulate bucket brigade 94 | float shDelta = (m_bins / (delay / m_sR)) / m_sR; // is this too slow? does m_sR cancel? :) 95 | if (shDelta >= 1.0f) 96 | { 97 | float n = ((rand() & 65535) - 32767.0) / (32767.0f); 98 | // TODO: Optimize noise 99 | m_shLast = in[i] + m_lastOut * m_feedback + n * m_noiseAmt; 100 | } 101 | else 102 | { 103 | m_shPos += shDelta; 104 | while (m_shPos >= 1.0f) 105 | { 106 | // TODO: Anti-aliasing pre-filter 107 | // TODO: Optimize noise 108 | float n = ((rand() & 65535) - 32767.0) / (32767.0f); 109 | m_shLast = in[i] + n * m_noiseAmt; 110 | m_shPos -= 1.0f; 111 | } 112 | } 113 | 114 | m_delBuf[m_wIndex] = m_shLast; 115 | // Linear interpolation between index int 1 & 2 depending 116 | // on amount of fraction 117 | out[i] = (m_delBuf[rIndexInt]*rIndexFrac + m_delBuf[rIndexInt2]*(1-rIndexFrac)); 118 | m_lastOut = out[i]; 119 | out[i] *= m_wet; 120 | m_wIndex = (m_wIndex + 1) % (m_bufSize); 121 | } 122 | 123 | m_postLP[0].Render(out, len); 124 | m_postLP[1].Render(out, len); 125 | m_postHP.Render(out, len); 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/components/Chorus.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHORUS_H_ 2 | #define _CHORUS_H_ 3 | 4 | #include "FilterBank.h" 5 | 6 | class Chorus 7 | { 8 | public: 9 | Chorus(); 10 | ~Chorus(); 11 | void SetSamplingRate(float sR); 12 | void RenderWet(float *in, float *out, int len); 13 | void SetMinDelay(float minDelay) { m_minDelay = minDelay; RecalcDelays(); } 14 | float GetMinDelay() { return m_minDelay; } 15 | void SetRange(float range) { m_range = range; RecalcDelays(); } 16 | float GetRange() { return m_range; } 17 | void SetLFORate(float hz) { m_lfoRate = hz; RecalcDelays(); } 18 | void SetWet(float wet) { m_wet = wet; } 19 | float GetWet() { return m_wet; } 20 | void SetBucketBins(int n) { m_bins = n; } 21 | void SetNoiseAmount(float x) { m_noiseAmt = x; } 22 | void SetOffset(float offset) { m_lfoPos = offset; } 23 | void SetFeedback(float fb) { m_feedback = fb; } 24 | float GetFeedback() { return m_feedback; } 25 | void SetTone(float prelp, float postlp, float hp) 26 | { 27 | m_preLP[0].SetFrequency(prelp); 28 | m_preLP[1].SetFrequency(prelp); 29 | m_postLP[0].SetFrequency(postlp); 30 | m_postLP[1].SetFrequency(postlp); 31 | m_postHP.SetFrequency(hp); 32 | } 33 | void RecalcDelays() 34 | { 35 | m_minDelaySamp = (m_minDelay/1000.0f)*m_sR; 36 | m_rangeSamp = (m_range/1000.0f)*m_sR; 37 | m_lfoDelta = m_lfoRate/m_sR; 38 | } 39 | 40 | private: 41 | // Delay buf. This should be enough 42 | // for a second and needs to be manually 43 | // resized when the buffer size changes 44 | // (not part of SndBuf's regular size). 45 | float* m_delBuf; 46 | // Write ptr 47 | int m_wIndex; 48 | 49 | float m_lfoPos; 50 | float m_lfoDelta; 51 | float m_lfoRate; 52 | 53 | float m_minDelay; 54 | float m_range; 55 | float m_minDelaySamp; 56 | float m_rangeSamp; 57 | float m_lastOut; 58 | 59 | float m_feedback; 60 | float m_sR; 61 | 62 | float m_wet; 63 | int m_bufSize; 64 | 65 | // Sample-hold for bucket brigade emulation 66 | float m_bins; 67 | float m_shLast; // last sample to hold 68 | float m_shPos; 69 | 70 | // Noise amount 71 | float m_noiseAmt; 72 | 73 | // Variables for pre and post anti-aliasing filters 74 | // (more bucket brigade emulation) 75 | // 6dB at 6khz 76 | LowPass1p m_preLP[2]; 77 | LowPass1p m_postLP[2]; 78 | LowPass1p m_triSmoother; 79 | HighPass m_postHP; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/components/Compressor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Compressor.cpp 3 | // DrumVST 4 | // 5 | // Created by Louis Gorenfeld on 10/2/16. 6 | // 7 | // 8 | 9 | #include "Compressor.h" 10 | 11 | Compressor::Compressor() : 12 | m_envFollowPos(0), 13 | m_attack(0), 14 | m_release(0), 15 | m_threshold(1.0), 16 | m_ratio(1.0/3.0) 17 | { 18 | } 19 | 20 | void Compressor::SetSamplingRate(float sR) 21 | { 22 | m_sR = sR; 23 | } 24 | 25 | void Compressor::Render(float *buf, int len) 26 | { 27 | float level; 28 | float peakLevel = 0; 29 | 30 | for (int i=0; i < len; i++) 31 | { 32 | level = buf[i]; 33 | if (level > peakLevel) 34 | peakLevel = level; 35 | else 36 | peakLevel *= .9999; 37 | 38 | if (peakLevel > m_threshold) 39 | { 40 | // Instant attack; release determined in part by peaklevel fall 41 | buf[i] *= 1.0 + ((peakLevel - m_threshold) * m_ratio); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/components/Compressor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Compressor.h 3 | // DrumVST 4 | // 5 | // Created by Louis Gorenfeld on 10/2/16. 6 | // 7 | // 8 | 9 | #ifndef Compressor_h 10 | #define Compressor_h 11 | 12 | class Compressor 13 | { 14 | public: 15 | Compressor(); 16 | ~Compressor(); 17 | void SetSamplingRate(float sR); 18 | void Render(float *buf, int len); 19 | void SetThreshold(float threshold) { m_threshold = threshold; } 20 | void SetRatio(float ratio) { m_ratio = ratio; } 21 | 22 | private: 23 | float m_envFollowPos; 24 | float m_attack; 25 | float m_release; 26 | float m_threshold; // dB 27 | float m_ratio; 28 | }; 29 | 30 | #endif /* Compressor_h */ 31 | -------------------------------------------------------------------------------- /src/components/Contour.cpp: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #include 4 | #include "SndBuf.h" 5 | #include "Contour.h" 6 | 7 | Contour::Contour() : 8 | m_curValue(0), 9 | m_attack(1.0), 10 | m_decay(1.0), 11 | m_release(1.0), 12 | m_fade(0), 13 | m_sustain(false), 14 | m_sustainLevel(1.0), 15 | m_min(0), 16 | m_max(1.0), 17 | m_phase(kFinished), 18 | m_ctlIn(1.0f), 19 | m_ctlVal(1.0f), 20 | m_lastOut(0), 21 | m_noAttack(false) 22 | { 23 | m_decay1TimesSusLevel = m_decay1 * m_sustainLevel; 24 | } 25 | 26 | inline float Contour::Clip(float x) 27 | { 28 | if (x < 0) 29 | return 0; 30 | else if (x > 1.0f) 31 | return 1.0f; 32 | 33 | return x; 34 | } 35 | 36 | 37 | void Contour::Render(float *out, int len) 38 | { 39 | float range = m_max - m_min; 40 | float min = m_min; 41 | 42 | if (!out) 43 | return; 44 | 45 | assert(m_attack != 0); 46 | assert(m_release != 0); 47 | 48 | for (int i=0; i= .98) 59 | { 60 | m_curValue = .98; 61 | m_phase = kDecay; 62 | } 63 | } 64 | else if (m_phase == kDecay) 65 | { 66 | m_curValue = (m_decay*m_lastOut) + m_decay1TimesSusLevel; 67 | m_lastOut = m_curValue; 68 | 69 | if (m_curValue <= m_sustainLevel) 70 | { 71 | if (m_sustain) 72 | { 73 | m_phase = kSustain; 74 | } 75 | else 76 | { 77 | m_phase = kRelease; 78 | } 79 | } 80 | } 81 | else if (m_phase == kSustain) 82 | { 83 | m_curValue = (m_fade*m_lastOut); 84 | m_lastOut = m_curValue; 85 | if (m_curValue <= 0.001) 86 | { 87 | m_phase = kFinished; 88 | m_curValue = 0; 89 | m_lastOut = 0; 90 | } 91 | } 92 | else if (m_phase == kRelease) 93 | { 94 | m_curValue = (m_release*m_lastOut); 95 | m_lastOut = m_curValue; 96 | 97 | if (m_curValue <= 0.001) 98 | { 99 | m_phase = kFinished; 100 | m_curValue = 0; 101 | m_lastOut = 0; 102 | } 103 | } 104 | 105 | // TODO: Vary this with the sampling rate. It's really just 106 | // a smoothing function, so it's probably OK for now 107 | m_ctlVal = m_ctlVal*.99 + m_ctlIn*.01; 108 | 109 | *out++ = Clip(min + m_curValue * range * m_ctlVal); 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/components/Contour.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | 4 | #ifndef _CONTOUR_H_ 5 | #define _CONTOUR_H_ 6 | 7 | #include 8 | #include "SndBuf.h" 9 | #include "BufferManager.h" 10 | 11 | // Linear trapezoidal contour generator 12 | // (wow, that makes it sounds so much more complex than it is!) 13 | class Contour 14 | { 15 | public: 16 | Contour(); 17 | ~Contour() {} 18 | 19 | // Set attack in ms 20 | void SetAttackExponential(float a, float sR) 21 | { 22 | float sams = (a/1000.0)*sR; 23 | m_attack = pow((float)M_E, (float)-1.0f/sams); 24 | m_attack1 = 1.0f - m_attack; 25 | } 26 | // Set Decay in ms, return seconds Release 27 | float SetDecayExponential(float d, float sR) 28 | { 29 | float sams = (d/1000.0)*sR; 30 | m_decay = pow((float)M_E, (float)-1.0f/sams); 31 | m_decay1 = 1.0f - m_decay; 32 | m_decay1TimesSusLevel = m_decay1*m_sustainLevel; 33 | 34 | sams = log(.001)/log(m_release); 35 | return (sams*1000.0f) / sR; 36 | } 37 | // Set Release in ms, return seconds Release 38 | float SetReleaseExponential(float d, float sR) 39 | { 40 | float sams = (d/1000.0)*sR; 41 | m_release = pow((float)M_E, (float)-1.0f/sams); 42 | m_release1 = 1.0f - m_release; 43 | 44 | sams = log(.001)/log(m_release); 45 | return (sams*1000.0f) / sR; 46 | } 47 | void SetFadeDirect(float f) 48 | { 49 | m_fade = f; 50 | m_fade1 = 1.0f - m_fade; 51 | m_sustain = (f > 0); 52 | } 53 | void SetFadeExponential(float f, float sR) 54 | { 55 | float sams = (f/1000.0)*sR; 56 | m_fade = pow((float)M_E, (float)-1.0f/sams); 57 | m_fade1 = 1.0f - m_fade; 58 | m_sustain = (f > 0); 59 | } 60 | // level is amplitude from 0 to 1.0 61 | void SetSustainLevel(float level) 62 | { 63 | m_sustainLevel = level; 64 | m_decay1TimesSusLevel = m_decay1*m_sustainLevel; 65 | } 66 | void SetMinimum(float min) { m_min = min; } 67 | void SetMaximum(float max) { m_max = max; } 68 | // Render REPLACING 69 | void Render(float *out, int len); 70 | SndBuf::sam_t GetValue() { return m_curValue; } 71 | 72 | void GateOn(bool reset=true) 73 | { 74 | if (reset) 75 | { 76 | m_lastOut = 0; 77 | m_curValue = m_noAttack? 1.0f : 0.0f; 78 | } 79 | m_phase = kAttack; 80 | } 81 | void GateOff() 82 | { 83 | if (m_phase != kFinished) 84 | { 85 | m_phase = kRelease; 86 | } 87 | } 88 | bool IsDone() { return m_phase == kFinished; } 89 | bool IsReleased() { return m_phase == kRelease; } 90 | void SetDone() { m_phase = kFinished; } 91 | inline float Clip(float x); 92 | 93 | void NoAttack(bool on=true) { m_noAttack = on; } 94 | 95 | // A control (such as modwheel) can be hooked to this to control 96 | // the brightness of the sound. The envelope wave is then multiplied 97 | // by it. It is smoothed to prevent clicking. 98 | inline void SetControlInput(float in) 99 | { 100 | m_ctlIn = in; 101 | } 102 | 103 | private: 104 | enum phase_t 105 | { 106 | kAttack, 107 | kDecay, 108 | kSustain, // ..and fade 109 | kRelease, 110 | kFinishing, 111 | kFinished, 112 | }; 113 | 114 | SndBuf::sam_t m_curValue; 115 | float m_attack; 116 | float m_decay; 117 | float m_release; 118 | float m_fade; 119 | bool m_sustain; 120 | float m_sustainLevel; 121 | float m_min; 122 | float m_max; 123 | phase_t m_phase; 124 | // Discrete control value input here to control brightness 125 | float m_ctlIn; 126 | // Smoothed control value 127 | float m_ctlVal; 128 | 129 | // Coefficients and such the one-pole exponential glide filter 130 | float m_attack1; 131 | float m_decay1; 132 | float m_release1; 133 | float m_fade1; 134 | float m_lastOut; 135 | 136 | // m_decay1 * m_sustainLevel used for envelope decay calculation 137 | float m_decay1TimesSusLevel; 138 | 139 | bool m_noAttack; 140 | }; 141 | 142 | #endif 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/components/FauxVst.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FauxVst.h 3 | * PDVST 4 | * 5 | * Created by Louis Gorenfeld on 9/18/12. 6 | * Copyright 2012 Extent of the Jam. All rights reserved. 7 | * 8 | */ 9 | 10 | // This header is intended to get Digits to compile for non-VST 11 | // builds. It's essentially a stub. DO NOT use it to figure out 12 | // the VST SDK since it diverges from the VST SDK spec 13 | 14 | #ifndef _FAUX_VST_H_ 15 | #define _FAUX_VST_H_ 16 | 17 | #define vst_strncpy strncpy 18 | #define vst_strncat strncat 19 | 20 | typedef int VstInt32; 21 | typedef int* VstIntPtr; 22 | 23 | // This is not used, but it should be non-zero when instantiating 24 | // the plugin (just set it to 1 or something) 25 | typedef void* audioMasterCallback; 26 | 27 | const int kVstMaxProgNameLen = 128; 28 | const int kVstMaxParamStrLen = 128; 29 | const int kVstMaxEffectNameLen = 128; 30 | const int kVstMaxVendorStrLen = 128; 31 | const int kVstMaxProductStrLen = 128; 32 | 33 | // Dummy declarations to make the compiler happy 34 | const int kVstMidiType = 0; 35 | const int kVstPinIsStereo = 0; 36 | const int kVstPinIsActive = 0; 37 | 38 | struct VstPinProperties 39 | { 40 | char label[kVstMaxParamStrLen]; 41 | int flags; 42 | }; 43 | 44 | struct VstMidiEvent 45 | { 46 | // NOTE: The official SDK uses 4 elements here 47 | char midiData[3]; 48 | int deltaFrames; 49 | int type; 50 | 51 | VstMidiEvent() { type = kVstMidiType; } 52 | }; 53 | 54 | struct VstEvents 55 | { 56 | int numEvents; 57 | // Only support VstMidiEvents for now 58 | VstMidiEvent *events[2]; 59 | }; 60 | 61 | class AudioEffect 62 | { 63 | public: 64 | AudioEffect() {} 65 | ~AudioEffect() {} 66 | }; 67 | 68 | class AudioEffectX : public AudioEffect 69 | { 70 | public: 71 | AudioEffectX(audioMasterCallback audioMaster, int numPatches, int numParameters) {} 72 | ~AudioEffectX() {} 73 | 74 | protected: 75 | void setNumInputs(int num) {} 76 | void setNumOutputs(int num) {} 77 | void canProcessReplacing() {} 78 | void isSynth() {} 79 | void setUniqueID(int id) {} 80 | void programsAreChunks(bool yeah) {} 81 | void suspend() {} 82 | void resume() {} 83 | void updateDisplay() {} 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/components/FilterBank.h: -------------------------------------------------------------------------------- 1 | // 2 | // FilterBank.h 3 | // PDVST 4 | // 5 | // Created by Louis Gorenfeld on 11/16/12. 6 | // 7 | // 8 | 9 | #ifndef __PDVST__FilterBank__ 10 | #define __PDVST__FilterBank__ 11 | 12 | // 13 | // FilterBank.cpp 14 | // PDVST 15 | // 16 | // Created by Louis Gorenfeld on 11/16/12. 17 | // 18 | // 19 | 20 | #include 21 | #include "FilterBank.h" 22 | 23 | class FilterBase 24 | { 25 | public: 26 | FilterBase() {} 27 | ~FilterBase() {} 28 | inline void SetSharpness() {} // aka bandwidth, q, resonance 29 | inline void SetFrequency() {}; 30 | virtual void SetSamplingRate(float f) { m_sR = f; } 31 | 32 | // If a filter has a control buffer (e.g., brightness), set it with this 33 | virtual void SetControlBuffer(float *buf) { } 34 | 35 | protected: 36 | float m_sR; 37 | }; 38 | 39 | // No-resonance 1-pole lowpass filter 40 | class LowPass1p : public FilterBase 41 | { 42 | public: 43 | LowPass1p() : m_a(0), m_b(0), m_lastOut(0) {} 44 | ~LowPass1p() {} 45 | // virtual void SetControlBuffer(float *buf) { m_freqContour = buf; } 46 | inline void SetFrequency(float f) 47 | { 48 | // TODO: Table this? 49 | m_frequency = f; 50 | m_b = exp(-2.0f * M_PI * (f/m_sR)); 51 | m_a = 1.0f - m_b; 52 | 53 | } 54 | inline float Tick(float in) 55 | { 56 | return m_lastOut = m_a*in + m_b*m_lastOut; 57 | } 58 | virtual void SetSamplingRate(float f) 59 | { 60 | m_sR = f; 61 | SetFrequency(m_frequency); 62 | } 63 | void Render(float* buf, int len) 64 | { 65 | for (int i=0; i 1.0f) return 1.0f; 354 | else if (x < -1.0f) return -1.0f; 355 | return x; 356 | } 357 | virtual void SetSamplingRate(float f) 358 | { 359 | m_sR = f * m_oversampling; 360 | m_lbFilter.SetSamplingRate(f); 361 | SetFrequency(m_frequency); 362 | } 363 | 364 | inline void SetSharpness(float x) { m_reso = x; } 365 | inline float Tick(float in) 366 | { 367 | for (int i=0; i < m_oversampling; i++) 368 | { 369 | m_lastOuts[0] = Clip(m_a*in + m_b*m_lastOuts[0] - ((m_reso*m_a)*(m_lbFilter.Tick(m_lastOuts[3])))); 370 | m_lastOuts[1] = Clip(m_a*m_lastOuts[0] + m_b*m_lastOuts[1]); 371 | m_lastOuts[2] = Clip(m_a*m_lastOuts[1] + m_b*m_lastOuts[2]); 372 | m_lastOuts[3] = Clip(m_a*m_lastOuts[2] + m_b*m_lastOuts[3]); 373 | } 374 | 375 | return m_lastOuts[m_poles]; 376 | } 377 | void Render(float* buf, int len) 378 | { 379 | for (int i=0; i 4) 389 | return false; 390 | 391 | m_poles = poles - 1; 392 | return true; 393 | } 394 | void SetOversampling(int times) { m_oversampling = times; } 395 | 396 | private: 397 | // virtual void SetFrequency(float f) 398 | 399 | float m_lastOuts[4]; 400 | int m_poles; // 0 (6db) to 3 (24db) 401 | 402 | float m_reso; 403 | float m_oversampling; 404 | LowPass1p m_lbFilter; 405 | }; 406 | 407 | #endif /* defined(__PDVST__FilterBank__) */ 408 | 409 | -------------------------------------------------------------------------------- /src/components/LFO.h: -------------------------------------------------------------------------------- 1 | #ifndef _LFO_H_ 2 | #define _LFO_H_ 3 | 4 | #include 5 | #include 6 | #include "Tables.h" 7 | 8 | class LFO 9 | { 10 | public: 11 | enum lfoType_t 12 | { 13 | kLFO_Sin, 14 | kLFO_Noise, 15 | kLFO_RampUp, 16 | kLFO_RampDn 17 | }; 18 | 19 | LFO() : m_type(kLFO_Sin), m_pos(0), m_thisNoise(0), m_lastNoise(0), m_delay(0), m_repeatCountDn(-1), m_repeatSetting(-1) {} 20 | ~LFO() {} 21 | void Render(float *out, int len) 22 | { 23 | for (int i=0; i 0) 30 | { 31 | out[i] = 0; 32 | m_delay--; 33 | } 34 | else if (m_type == kLFO_Sin) 35 | { 36 | out[i] = Tables::Sin(m_pos); 37 | m_pos += m_delta; 38 | } 39 | else if (m_type == kLFO_Noise) 40 | { 41 | // If the rate is above 40hz, start smoothing it (TODO, get rate :)) 42 | // TODO: Use better equation (too lazy to think right now) 43 | out[i] = (m_lastNoise * (1.0f-m_pos)) + (m_thisNoise * m_pos); 44 | m_pos += m_delta; 45 | } 46 | else if (m_type == kLFO_RampDn) 47 | { 48 | out[i] = (m_pos - 1.0f); 49 | m_pos += m_delta; 50 | } 51 | else if (m_type == kLFO_RampUp) 52 | { 53 | out[i] = (1.0f - m_pos); 54 | m_pos += m_delta; 55 | } 56 | 57 | while (m_pos >= 1.0f) 58 | { 59 | if (m_type == 1) 60 | { 61 | m_lastNoise = m_thisNoise; 62 | // Normal distribution 63 | m_thisNoise = (((rand())&65535)/32767.0f)-1.0f; 64 | m_thisNoise += (((rand())&65535)/32767.0f)-1.0f; 65 | m_thisNoise /= 2.0f; 66 | } 67 | // Don't go past 0 (see comparison at beginning of fn) 68 | if (m_repeatCountDn > 0) 69 | m_repeatCountDn--; 70 | m_pos -= 1.0f; 71 | } 72 | } 73 | } 74 | void Reset() { m_pos = 0; m_delay = m_delayInit; m_repeatCountDn = m_repeatSetting; } 75 | void SetRate(float rate, float sR) { m_delta = rate/sR; } 76 | void SetDelay(float delayMs, float sR) { m_delayInit = m_delay = (delayMs*sR)/1000.0f; } 77 | void SetType(lfoType_t type) { m_type = type; } 78 | void SetRepeat(int repeat) { m_repeatSetting = repeat; } 79 | lfoType_t GetType() { return m_type; } 80 | 81 | private: 82 | lfoType_t m_type; 83 | float m_delta; 84 | float m_pos; 85 | float m_thisNoise; 86 | float m_lastNoise; 87 | int m_delay; 88 | int m_delayInit; 89 | // -1 for infinite 90 | int m_repeatCountDn; 91 | int m_repeatSetting; 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/components/LGDebug.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _LGDEBUG_H_ 3 | #define _LGDEBUG_H_ 4 | 5 | #include 6 | #include 7 | 8 | 9 | // The following is cribbed from the GCC manual: 10 | 11 | /* Subtract the `struct timeval' values X and Y, 12 | storing the result in RESULT. 13 | Return 1 if the difference is negative, otherwise 0. */ 14 | 15 | int 16 | timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); 17 | 18 | class CPUBench 19 | { 20 | public: 21 | CPUBench() 22 | { 23 | gettimeofday(&m_start, 0); 24 | } 25 | 26 | ~CPUBench() 27 | { 28 | usec_t curTime; 29 | 30 | gettimeofday(&m_finish, 0); 31 | 32 | struct timeval diff; 33 | timeval_subtract(&diff, &m_finish, &m_start); 34 | curTime = (diff.tv_sec*1000000) + diff.tv_usec; 35 | 36 | if (s_peak < curTime) 37 | s_peak = curTime; 38 | 39 | s_sum += curTime; 40 | s_numBufs++; 41 | } 42 | 43 | // Reset the value for a new frame 44 | void Reset() 45 | { 46 | s_sum = 0; 47 | s_numBufs = 0; 48 | s_peak = 0; 49 | } 50 | 51 | // Print out the CPU% given the length of the buffer 52 | static void Print(float bufUs) 53 | { 54 | printf("Average: %02.2f; Peak: %02.2f\n", (((float)s_sum/(float)s_numBufs)/bufUs)*100, ((float)s_peak/bufUs)*100); 55 | // It's kind of weird to set lastAverage here, but it's convinient 56 | s_lastAverage = (((float)s_sum/(float)s_numBufs)/bufUs)*100; 57 | } 58 | 59 | static float GetLastAverage() { return s_lastAverage; } 60 | 61 | private: 62 | typedef long int usec_t; 63 | 64 | // Beginning and end of the interval currently measured 65 | struct timeval m_start; 66 | struct timeval m_finish; 67 | 68 | // Running sum of all the buffers so far 69 | static usec_t s_sum; 70 | // Number of buffers in sum 71 | static int s_numBufs; 72 | 73 | // Peak - worst buffer length so far 74 | static usec_t s_peak; 75 | 76 | static float s_lastAverage; 77 | }; 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/components/NoiseGen.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // NoiseGen.cpp 3 | // DrumVST 4 | // 5 | // Created by Louis Gorenfeld on 10/16/16. 6 | // 7 | // 8 | 9 | #include "NoiseGen.h" 10 | #include "Tables.h" 11 | 12 | NoiseGen::NoiseGen() : 13 | m_pos(0), 14 | m_delta(0) 15 | { 16 | 17 | } 18 | 19 | NoiseGen::~NoiseGen() 20 | { 21 | 22 | } 23 | 24 | void NoiseGen::SetSamplingRate(float sR) 25 | { 26 | m_delta = Tables::kNoiseRate / sR; 27 | } 28 | 29 | void NoiseGen::Render(float *out, int len) 30 | { 31 | for (int i=0; i < len; i++) 32 | { 33 | out[i] = Tables::Noise(m_pos); 34 | 35 | m_pos += m_delta; 36 | while (m_pos >= Tables::kNoisePoints) 37 | m_pos -= Tables::kNoisePoints; 38 | } 39 | } 40 | 41 | void NoiseGen::Trigger() 42 | { 43 | m_pos = rand() & Tables::kNoisePoints; 44 | } 45 | -------------------------------------------------------------------------------- /src/components/NoiseGen.h: -------------------------------------------------------------------------------- 1 | // 2 | // NoiseGen.h 3 | // DrumVST 4 | // 5 | // Created by Louis Gorenfeld on 10/16/16. 6 | // 7 | // 8 | 9 | #ifndef NoiseGen_h 10 | #define NoiseGen_h 11 | 12 | class NoiseGen 13 | { 14 | public: 15 | NoiseGen(); 16 | ~NoiseGen(); 17 | void Render(float *out, int len); 18 | void SetSamplingRate(float sR); 19 | void Trigger(); 20 | 21 | private: 22 | float m_pos; 23 | float m_delta; 24 | }; 25 | 26 | 27 | #endif /* NoiseGen_h */ 28 | -------------------------------------------------------------------------------- /src/components/Oversampler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Oversampler.h" 6 | 7 | 8 | Oversampler::Oversampler(int kernelSize, int times) : 9 | m_kernelSize(kernelSize), 10 | m_bufPos(0), 11 | m_times(times) 12 | 13 | { 14 | float cutoff = .5 / (float)times; 15 | 16 | m_kernel = new float[kernelSize]; 17 | m_ins = new float[kernelSize]; 18 | for (int i=0; i < kernelSize; i++) 19 | { 20 | float idx = i - (kernelSize/2.0); 21 | float winPos = (float)i / (float)kernelSize; 22 | 23 | // Blackman window 24 | float window = .42 - .5*cos(2.0*M_PI*winPos) + .08*cos(4.0*M_PI*winPos); 25 | 26 | if (idx == 0) 27 | m_kernel[i] = 2.0*M_PI*cutoff; 28 | else 29 | m_kernel[i] = sin(2.0*M_PI*cutoff*idx) / idx; 30 | 31 | m_kernel[i] *= window; 32 | m_ins[i] = 0; 33 | } 34 | 35 | // Normalize the kernels 36 | float sum = 0; 37 | for (int i=0; i < kernelSize; i++) 38 | sum += m_kernel[i]; 39 | 40 | for (int i=0; i < kernelSize; i++) 41 | m_kernel[i] /= sum; 42 | } 43 | 44 | 45 | void Oversampler::render(float *in, float *out, int numInSamples) 46 | { 47 | memset(out, 0, sizeof(float)*numInSamples); 48 | 49 | for (int i=0; i < numInSamples; i+=m_times) 50 | { 51 | m_ins[m_bufPos] = *in++; 52 | 53 | int pos = m_bufPos; 54 | for (int j=0; j < m_kernelSize; j++) 55 | { 56 | *out += m_ins[pos] * m_kernel[j]; 57 | if (--pos < 0) 58 | pos += m_kernelSize; 59 | } 60 | 61 | out++; 62 | m_bufPos = (m_bufPos + 1) % m_kernelSize; 63 | } 64 | } 65 | 66 | Oversampler::~Oversampler() 67 | { 68 | delete[] m_kernel; 69 | delete[] m_ins; 70 | } 71 | 72 | 73 | 74 | // For testing 75 | 76 | // OPTIMIZE: If we're going down to 1/8th of sR, every 4th sample in the filter is 0 (1/4 of Nyquist) 77 | // So, we can skip those. We could unroll it. We can also skip every 4th output sample. 78 | /* 79 | int main() 80 | { 81 | //WinSincFilter filter(128, .015); 82 | Oversampler filter(64, .125); 83 | float noise[44100]; 84 | float out[44100]; 85 | 86 | float pos = 0; 87 | 88 | for (int i=0; i < 44100; i++) 89 | { 90 | noise[i] = sin(M_PI*2.0*pos); 91 | pos += 8000/44100.0; 92 | } 93 | 94 | // for (int i=0; i < 44100; i++) 95 | // noise[i] = ((rand() & 255) - 127) / 127.0f; 96 | 97 | filter.render(noise, out, 44100, 1); 98 | 99 | FILE *fp = fopen("test.raw", "wb"); 100 | fwrite(out, sizeof(float), 44100, fp); 101 | 102 | fclose(fp); 103 | } 104 | */ 105 | -------------------------------------------------------------------------------- /src/components/Oversampler.h: -------------------------------------------------------------------------------- 1 | #ifndef _OVERSAMPLER_H_ 2 | #define _OVERSAMPLER_H_ 3 | 4 | // Straight-forward non-convolving sinc filter 5 | class Oversampler 6 | { 7 | public: 8 | Oversampler(int kernelSize, int times); 9 | ~Oversampler(); 10 | 11 | void render(float *in, float *out, int numInSamples); 12 | 13 | private: 14 | int m_kernelSize; 15 | int m_bufPos; 16 | int m_times; 17 | float *m_kernel; 18 | float *m_ins; 19 | }; 20 | 21 | #endif -------------------------------------------------------------------------------- /src/components/PatchBankList.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PatchBankList.h 3 | * PDVST 4 | * 5 | * Created by Louis Gorenfeld on 8/18/12. 6 | * Copyright 2012 Extent of the Jam. All rights reserved. 7 | * 8 | */ 9 | 10 | // This is a generic interface for the patch bank list 11 | // Use a subclass to use this! 12 | 13 | // The class' job is to return a list of filenames. Upon 14 | // an error, it should return a blank list. 15 | 16 | // For legacy reasons, this module is called PatchBankList. 17 | // But, the implementation-specific PatchBankList files 18 | // (PatchBankListMac, PatchBankListWin) actually are the 19 | // ones that supply the PatchBankList class. These only 20 | // supply PatchBankListBase. 21 | 22 | #ifndef _PATCHBANKLIST_H_ 23 | #define _PATCHBANKLIST_H_ 24 | 25 | #include 26 | #include 27 | 28 | class PatchBankListBase 29 | { 30 | public: 31 | typedef std::vector fileList_t; 32 | 33 | PatchBankListBase() : m_curPatch(0), m_curBank(0), m_numPatches(0) {} 34 | ~PatchBankListBase() {} 35 | 36 | void SetBankDir(std::string dir) 37 | { 38 | m_curBankDir = dir; 39 | } 40 | 41 | void SetBankDir(int index) 42 | { 43 | m_curBankDir = m_bankListCache[index]; 44 | } 45 | 46 | virtual PatchBankListBase::fileList_t GetBankList() = 0; 47 | virtual PatchBankListBase::fileList_t GetPatchList() = 0; 48 | PatchBankListBase::fileList_t m_bankListCache; 49 | PatchBankListBase::fileList_t m_patchListCache; 50 | std::string GetCurBankDir() { return m_bankPrefix + "/" + m_curBankDir + "/"; } 51 | std::string GetUserBankDir() { return m_bankPrefix + "/" + "User"; } 52 | int GetCurBank() { return m_curBank; } 53 | std::string GetCurPatchName() 54 | { 55 | if (m_curPatch == -1 || m_patchListCache.size() == 0) 56 | return ""; 57 | else 58 | return m_patchListCache[m_curPatch]; 59 | } 60 | int GetCurPatch() { return m_curPatch; } 61 | int SetCurBankDir(std::string newDir) 62 | { 63 | m_curBankDir = newDir; 64 | 65 | unsigned int index = 0; 66 | for (PatchBankListBase::fileList_t::iterator it = m_bankListCache.begin(); 67 | it != m_bankListCache.end(); 68 | it++, index++) 69 | { 70 | if (*it == m_curBankDir) 71 | break; 72 | } 73 | 74 | if (index < m_bankListCache.size()) 75 | m_curBank = index; 76 | else 77 | m_curBank = -1; 78 | 79 | return m_curBank; 80 | } 81 | void SetCurBankDir(int index) { m_curBankDir = m_bankListCache[index]; } 82 | void SetCurPatch(int index) 83 | { 84 | if (m_patchListCache.size() > 0) 85 | { 86 | m_curPatch = index; 87 | m_curPatchName = m_patchListCache[index]; 88 | } 89 | } 90 | // When set like this, there's no knowledge of the patch index number. The EditorWindow will 91 | // try to correct it when it first opens. This function is only to be used during VstCore init. 92 | // Return now-current patch 93 | int SetCurPatch(std::string newPatch) 94 | { 95 | m_curPatchName = newPatch; 96 | 97 | unsigned int index = 0; 98 | for (PatchBankListBase::fileList_t::iterator it = m_patchListCache.begin(); 99 | it != m_patchListCache.end(); 100 | it++, index++) 101 | { 102 | if (*it == m_curPatchName) 103 | break; 104 | } 105 | 106 | if (index < m_patchListCache.size()) 107 | m_curPatch = index; 108 | else 109 | m_curPatch = -1; 110 | 111 | return m_curPatch; 112 | } 113 | // Get the *cached* number of patches. A bank must be set and a patch 114 | // list obtained before this is valid. 115 | int GetNumPatches() { return m_numPatches; } 116 | 117 | protected: 118 | // Path to the currently-selected bank directory 119 | std::string m_curBankDir; 120 | std::string m_curPatchName; 121 | // Path to where the banks can be found 122 | std::string m_bankPrefix; 123 | // Index of the current patch and bank 124 | int m_curPatch; 125 | int m_curBank; 126 | // Cache of the number of patches in the bank (to avoid 127 | // getting a file list each time) 128 | int m_numPatches; 129 | }; 130 | 131 | #ifdef _MSC_VER 132 | #include "PatchBankListWin.h" 133 | #elif __APPLE__ 134 | #include "PatchBankListMac.h" 135 | #else 136 | #warning "Creating empty PatchBankList implementation for this platform!" 137 | 138 | class PatchBankList : public PatchBankListBase 139 | { 140 | public: 141 | PatchBankList() {} 142 | ~PatchBankList() {} 143 | virtual PatchBankListBase::fileList_t GetBankList() 144 | { 145 | return PatchBankListBase::fileList_t(); 146 | } 147 | virtual PatchBankListBase::fileList_t GetPatchList() 148 | { 149 | return PatchBankListBase::fileList_t(); 150 | } 151 | }; 152 | #endif 153 | #endif // header compile-once 154 | -------------------------------------------------------------------------------- /src/components/PatchBankListMac.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PatchBankListMac.cpp 3 | * PDVST 4 | * 5 | * Created by Louis Gorenfeld on 8/18/12. 6 | * Copyright 2012 Extent of the Jam. All rights reserved. 7 | * 8 | */ 9 | 10 | #include // sort 11 | #include 12 | #include "PatchBankListMac.h" 13 | 14 | PatchBankList::PatchBankList() 15 | { 16 | m_bankPrefix = "/Applications/Digits/Presets"; 17 | } 18 | 19 | PatchBankList::~PatchBankList() 20 | { 21 | } 22 | 23 | PatchBankList::fileList_t PatchBankList::GetBankList() 24 | { 25 | return GetFileList(m_bankPrefix, true); 26 | } 27 | 28 | PatchBankList::fileList_t PatchBankList::GetPatchList() 29 | { 30 | PatchBankList::fileList_t files = GetFileList(m_bankPrefix + "/" + m_curBankDir); 31 | m_numPatches = files.size(); 32 | return files; 33 | } 34 | 35 | PatchBankList::fileList_t PatchBankList::GetFileList(std::string dirStr, bool isBankList) 36 | { 37 | PatchBankList::fileList_t* files; 38 | if (isBankList) 39 | { 40 | m_bankListCache.clear(); 41 | files = &m_bankListCache; 42 | } 43 | else 44 | { 45 | m_patchListCache.clear(); 46 | files = &m_patchListCache; 47 | } 48 | 49 | DIR* dir = opendir(dirStr.c_str()); 50 | struct dirent* file; 51 | 52 | if (!dir) 53 | { 54 | files->push_back(""); 55 | return *files; 56 | } 57 | 58 | while ((file = readdir(dir))) 59 | { 60 | if ((!isBankList && file->d_type == DT_REG) || (isBankList && file->d_type == DT_DIR)) 61 | { 62 | std::string stdname = file->d_name; 63 | if (stdname.at(0) == '.') 64 | continue; 65 | 66 | // strip '.fxp' 67 | if (!isBankList) 68 | { 69 | size_t pos = stdname.find(".fxp"); 70 | if (pos != std::string::npos) 71 | stdname = stdname.substr(0, pos); 72 | } 73 | 74 | files->push_back(stdname); 75 | } 76 | } 77 | 78 | if (files->size() == 0) 79 | files->push_back(""); 80 | 81 | std::sort(files->begin(), files->end()); 82 | 83 | closedir(dir); 84 | return *files; 85 | } 86 | -------------------------------------------------------------------------------- /src/components/PatchBankListMac.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PatchBankListMac.h 3 | * PDVST 4 | * 5 | * Created by Louis Gorenfeld on 8/18/12. 6 | * Copyright 2012 LouisGorenfeld. All rights reserved. 7 | * 8 | */ 9 | 10 | #ifndef _PATCHBANKLISTMAC_H_ 11 | #define _PATCHBANKLISTMAC_H_ 12 | 13 | #include "PatchBankList.h" // interface 14 | 15 | class PatchBankList : public PatchBankListBase 16 | { 17 | public: 18 | PatchBankList(); 19 | ~PatchBankList(); 20 | 21 | virtual PatchBankListBase::fileList_t GetBankList(); 22 | virtual PatchBankListBase::fileList_t GetPatchList(); 23 | 24 | private: 25 | static const char* s_banksPath; 26 | PatchBankListBase::fileList_t GetFileList(std::string dir, bool isBankList=false); 27 | }; 28 | 29 | #endif -------------------------------------------------------------------------------- /src/components/PatchBankListWin.cpp: -------------------------------------------------------------------------------- 1 | #include // sort 2 | #include 3 | #include // SHGetKnownFolderPath 4 | #include 5 | #include "PatchBankListWin.h" 6 | 7 | PatchBankList::PatchBankList() 8 | { 9 | TCHAR path[MAX_PATH]; 10 | if (SHGetFolderPath(0, CSIDL_MYDOCUMENTS, 0, NULL, path) == S_OK) 11 | { 12 | m_bankPrefix = (char*)path; 13 | m_bankPrefix += "/Extent of the Jam/Digits/Patches"; 14 | } 15 | } 16 | 17 | PatchBankList::~PatchBankList() 18 | { 19 | } 20 | 21 | PatchBankList::fileList_t PatchBankList::GetBankList() 22 | { 23 | return GetFileList(m_bankPrefix + "/*", true); 24 | } 25 | 26 | PatchBankList::fileList_t PatchBankList::GetPatchList() 27 | { 28 | PatchBankList::fileList_t files = GetFileList(m_bankPrefix + "/" + m_curBankDir + "/*", false); 29 | m_numPatches = files.size(); 30 | return files; 31 | } 32 | 33 | PatchBankList::fileList_t PatchBankList::GetFileList(std::string dirStr, bool isBankList) 34 | { 35 | PatchBankListBase::fileList_t fileList; 36 | WIN32_FIND_DATA findData; 37 | HANDLE hFind; 38 | 39 | PatchBankList::fileList_t* files; 40 | if (isBankList) 41 | { 42 | m_bankListCache.clear(); 43 | files = &m_bankListCache; 44 | } 45 | else 46 | { 47 | m_patchListCache.clear(); 48 | files = &m_patchListCache; 49 | } 50 | 51 | hFind = FindFirstFile(dirStr.c_str(), &findData); 52 | 53 | if (hFind != INVALID_HANDLE_VALUE) 54 | { 55 | do 56 | { 57 | if ((isBankList && findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 58 | || (!isBankList && !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))) 59 | { 60 | 61 | std::string stdname = findData.cFileName; 62 | if (stdname == "." || stdname == "..") 63 | continue; 64 | 65 | // strip '.fxp' 66 | if (!isBankList) 67 | { 68 | size_t pos = stdname.find(".fxp"); 69 | if (pos != std::string::npos) 70 | stdname = stdname.substr(0, pos); 71 | } 72 | 73 | files->push_back(stdname.c_str()); 74 | } 75 | } while (FindNextFile(hFind, &findData)); 76 | } 77 | 78 | std::sort(files->begin(), files->end()); 79 | 80 | return *files; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/components/PatchBankListWin.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATCHBANKLISTWIN_H_ 2 | #define _PATCHBANKLISTWIN_H_ 3 | 4 | #include 5 | #include "PatchBankList.h" 6 | 7 | class PatchBankList : public PatchBankListBase 8 | { 9 | public: 10 | PatchBankList(); 11 | ~PatchBankList(); 12 | virtual PatchBankListBase::fileList_t GetBankList(); 13 | virtual PatchBankListBase::fileList_t GetPatchList(); 14 | PatchBankListBase::fileList_t GetFileList(std::string dirStr, bool isBankList); 15 | }; 16 | 17 | #endif -------------------------------------------------------------------------------- /src/components/SndBuf.cpp: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #include "BufferManager.h" 4 | #include "SndBuf.h" 5 | #include "Tables.h" 6 | 7 | SndBuf::SndBuf(BufferManager &manager, std::string name) : 8 | m_manager(manager), 9 | m_name(name) 10 | { 11 | m_len = manager.GetHostBlockSize(); 12 | m_buf = new sam_t[m_len]; 13 | m_manager.AddBuffer(this); 14 | } 15 | /* 16 | SndBuf::SndBuf(BufferManager &manager, int len) : 17 | m_manager(manager), 18 | m_len(len) 19 | { 20 | m_buf = new sam_t[len]; 21 | memset(m_buf, 0, sizeof(sam_t)*len); 22 | m_manager.AddBuffer(this); 23 | } 24 | */ 25 | SndBuf::~SndBuf() 26 | { 27 | m_manager.RemoveBuffer(this); 28 | delete[] m_buf; 29 | } 30 | 31 | SndBuf::SndBuf(const SndBuf& b) : 32 | m_manager(b.m_manager) 33 | { 34 | m_len = b.m_len; 35 | memcpy(m_buf, b.m_buf, sizeof(sam_t)*b.m_len); 36 | } 37 | 38 | 39 | void SndBuf::Resize(int newSize) 40 | { 41 | if (m_buf) 42 | delete[] m_buf; 43 | m_buf = new sam_t[newSize]; 44 | Tables::ZeroMem(m_buf, newSize); 45 | m_len = newSize; 46 | } 47 | 48 | float SndBuf::GetSamplingRate() 49 | { 50 | return m_manager.GetSamplingRate(); 51 | } 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/components/SndBuf.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | /* The SndBuf class is responsible for allocating and deallocating its 4 | * buffer, but the BufferManager class will automatically resize every 5 | * buffer when the block size changes in the host */ 6 | 7 | #ifndef _SNDBUF_H_ 8 | #define _SNDBUF_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "Tables.h" 14 | 15 | class BufferManager; 16 | 17 | class SndBuf 18 | { 19 | public: 20 | typedef float sam_t; 21 | 22 | SndBuf(BufferManager &manager, std::string name); 23 | //SndBuf(BufferManager &manager, int len); 24 | ~SndBuf(); 25 | SndBuf(const SndBuf& buf); 26 | 27 | int Len() { return m_len; } 28 | sam_t* Data() { return m_buf; } 29 | void Resize(int newSize); 30 | // Return sampling rate from manager 31 | float GetSamplingRate(); 32 | // Zero out buffer 33 | inline void Zero() 34 | { 35 | Tables::ZeroMem(m_buf, m_len); 36 | } 37 | 38 | private: 39 | BufferManager &m_manager; 40 | // Length of the buffer in frames 41 | int m_len; 42 | // Sample data for the buffer 43 | sam_t *m_buf; 44 | // Name of the buffer to make debugging less hellish 45 | std::string m_name; 46 | }; 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /src/components/Tables.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Tables.h" 4 | 5 | float Tables::g_sinTab[kSinePoints+1]; 6 | float Tables::g_cosTab[kSinePoints+1]; 7 | float Tables::g_softClipTab[kSoftClipPoints+1]; 8 | float Tables::g_dbTab[kDbPoints+1]; 9 | float Tables::g_pulseTab[kPulsePoints]; 10 | float Tables::g_noiseTab[kNoisePoints+1]; 11 | 12 | void Tables::Init() 13 | { 14 | for (int i=0; i 5 | #include 6 | #ifdef __APPLE__ 7 | #include 8 | #endif 9 | 10 | // Tables and misc. globals 11 | 12 | namespace Tables 13 | { 14 | void Init(); 15 | 16 | // This goes from 0 to 1, unlike real sine 17 | // which goes from 0 to 2pi 18 | inline float Sin(float x); 19 | inline float Cos(float x); 20 | inline float Noise(float x); 21 | inline float dbToAmp(float x); 22 | 23 | inline float SoftClip(float x); 24 | inline void ZeroMem(float *buf, int len); 25 | 26 | const int kSinePoints = 8192; 27 | const int kPulsePoints = 4096; 28 | const float kNoiseRate = 30000; 29 | const int kNoisePoints = kNoiseRate * 4; 30 | extern float g_sinTab[kSinePoints+1]; 31 | extern float g_cosTab[kSinePoints+1]; 32 | extern float g_pulseTab[kPulsePoints]; 33 | 34 | // 1 entry for each 16-bit dB (interpolated when reading) 35 | const int kDbPoints = 96; 36 | extern float g_dbTab[kDbPoints+1]; 37 | 38 | const int kSoftClipPoints = 256; 39 | extern float g_softClipTab[kSoftClipPoints+1]; 40 | extern float g_noiseTab[kNoisePoints+1]; 41 | 42 | #ifdef DIGITS_PRO 43 | const int kNumLFOs = 3; 44 | #else 45 | const int kNumLFOs = 1; 46 | #endif 47 | }; 48 | 49 | inline float Tables::Noise(float x) 50 | { 51 | float dist = x - floor(x); 52 | int i = x; 53 | return g_noiseTab[i] + dist*(g_noiseTab[i+1] - g_noiseTab[i]); 54 | } 55 | 56 | inline float Tables::Sin(float x) 57 | { 58 | float fIndex = x*kSinePoints; 59 | 60 | // This profiled to be faster than fmod 61 | while (fIndex >= kSinePoints) 62 | fIndex -= kSinePoints; 63 | while (fIndex < 0) 64 | fIndex += kSinePoints; 65 | 66 | // Short circuit this function-- this is nearest neighbor. With 67 | // a 8k-entry table, there doesn't seem to be noticible noise and 68 | // it uses less CPU than, say, a 256-entry table with interpolation 69 | // below (on an Intel i5) 70 | return g_sinTab[(int)fIndex]; 71 | 72 | #if 0 73 | float frac = fIndex - int(fIndex); 74 | int index = fIndex; 75 | float ret = g_sinTab[index] + ( g_sinTab[index+1] - g_sinTab[index] )*frac; 76 | 77 | return ret; 78 | #endif 79 | } 80 | 81 | inline float Tables::Cos(float x) 82 | { 83 | // Cribbed from Sin()-- go see comments there 84 | float fIndex = x*kSinePoints; 85 | 86 | // This profiled to be faster than fmod 87 | while (fIndex >= kSinePoints) 88 | fIndex -= kSinePoints; 89 | while (fIndex < 0) 90 | fIndex += kSinePoints; 91 | // if (x == NAN) { printf("NAN2 from x = %f\n", x); return 0; } 92 | 93 | 94 | return g_cosTab[(int)fIndex]; 95 | } 96 | 97 | inline float Tables::SoftClip(float x) 98 | { 99 | 100 | float fIndex = ((x + 1.0f)/2.0f) * (float)kSoftClipPoints; 101 | int index = (int)fIndex; 102 | float frac = fIndex - index; 103 | return g_softClipTab[index] + (g_softClipTab[index+1] - g_softClipTab[index]) * frac; 104 | } 105 | 106 | inline void Tables::ZeroMem(float *buf, int len) 107 | { 108 | #ifdef __APPLE__ 109 | vDSP_vclr(buf, 1.0, len); 110 | #else 111 | for (int i=0; i */ 2 | 3 | #include "Voice.h" 4 | #include "VstCore.h" 5 | 6 | #ifdef DIGITS_MULTICORE 7 | #include // EBUSY for trylock 8 | #include 9 | #endif 10 | 11 | float Voice::kAttackRange = 1000.0f; 12 | float Voice::kAttackMinimumAmp = 1.0f; 13 | float Voice::kAttackMinimumShaper = 1.0f; 14 | float Voice::kDecayRange = 1000.0f; 15 | float Voice::kDecayMinimum = 20.0f; 16 | float Voice::kReleaseRange = 1000.0f; 17 | float Voice::kReleaseMinimum = 20.0f; 18 | float Voice::kFadeRange = 3000.0f; 19 | float Voice::kFadeMinimum = 500.0f; 20 | float Voice::kDetuneMaximum = .01f; 21 | float Voice::kLFOMinimum = .25f; //hz 22 | float Voice::kLFORange = 1000.0f; //well into audio range 23 | float Voice::kPWMMinimum = .1f; 24 | float Voice::kPWMRange = .8f; 25 | 26 | #ifdef DBGMCORE 27 | #define DEBUG_MCORE(...) { fprintf(stderr, __VA_ARGS__); } 28 | #else 29 | #define DEBUG_MCORE 30 | #endif 31 | 32 | // This is to shape parameter space so, for example, the slider for 33 | // an envelope has more "short decay" options than long ones. This 34 | // makes controls with a lot of range much easier to use. 35 | inline float ExpShape(float base, float x) 36 | { 37 | float range = base - 1; 38 | return ((pow(base, x) - 1.0f)/range); 39 | } 40 | 41 | Voice::Voice(int voiceNum) : 42 | m_pdOsc1(), 43 | m_pdOsc2(), 44 | m_pitch(0), 45 | m_detune(0), 46 | m_octave(1.0f), 47 | m_mix(.5f), 48 | m_resoVol(0), 49 | m_pulseWidth(.5f), 50 | m_delta(0), 51 | m_deltaLo(0), 52 | m_deltaHi(0), 53 | m_delta2(0), 54 | m_deltaLo2(0), 55 | m_deltaHi2(0), 56 | m_deltaBlend(0), 57 | m_glideSpeed(0), 58 | m_glideMode(kGlide_PolyNoGlide), 59 | m_bend(0), 60 | m_modWheel(0), 61 | m_aftertouch(0), 62 | m_velocity(0), 63 | m_basisWave(0), 64 | m_shpMin(0), 65 | m_shpMax(0), 66 | m_velShp(0), 67 | m_velAmp(0), 68 | m_modShp(0), 69 | m_modLFO1Amp(0), 70 | m_atouchShp(0), 71 | m_atouchLFO1Amp(0), 72 | m_nextSubVoice(0), 73 | m_needsRender(false), 74 | m_isSubVoice(false), 75 | m_lockShaperAmt(0), 76 | m_sR(0), 77 | m_voiceNumber(voiceNum), 78 | m_ampRateScale(0), 79 | m_ampLevelScale(0), 80 | m_ampAttack(0), 81 | m_ampDecay(0), 82 | m_ampRelease(0), 83 | m_shpRateScale(0), 84 | m_shpLevelScale(0), 85 | m_shpAttack(0), 86 | m_shpDecay(0), 87 | m_shpRelease(0), 88 | m_bitCrushPos(0), 89 | m_bitCrushDelta(0), 90 | m_bitCrushBlend(0), 91 | m_bitCrushDivider(0), 92 | m_bitCrushBits(0) 93 | { 94 | #ifdef DIGITS_MULTICORE 95 | pthread_mutex_init(&m_mutex, 0); 96 | #endif 97 | 98 | m_delta = m_deltaHi = m_deltaLo = 0; 99 | 100 | m_pdOsc1.SetSkew(.5); 101 | m_pdOsc2.SetSkew(.99); 102 | 103 | for (int i=0; i 1.0f) levelScale = 1.0f; 137 | 138 | // TODO: Don't pass delta in; might as well do it all at once 139 | 140 | if (reset) 141 | { 142 | ResetPhases(); 143 | } 144 | m_ampEnv.GateOn(false); 145 | m_shaperEnv.GateOn(false); 146 | for (int i=0; i= 400) 171 | { 172 | // Intercept (400, 1) and (1200, 0) 173 | 174 | keyScale = 1.0 - (x - 400.0f)/6000.0f; 175 | if (keyScale < 0) keyScale = 0; 176 | } 177 | else { 178 | keyScale = 1.0f; 179 | } 180 | 181 | m_pdOsc1.SetKeyScale(keyScale*levelScale); 182 | 183 | x = m_pdOsc2.GetDelta()*m_sR; 184 | if (x >= 400) 185 | { 186 | // Intercept (400, 1) and (1200, 0) 187 | 188 | keyScale = 1.0 - (x - 400.0f)/6000.0f; 189 | if (keyScale < 0) keyScale = 0; 190 | } 191 | else { 192 | keyScale = 1.0f; 193 | } 194 | 195 | m_pdOsc2.SetKeyScale(keyScale*levelScale); 196 | } 197 | 198 | void Voice::NoteOff(int key) 199 | { 200 | if (key != m_pitch && key >= 0) 201 | return; 202 | 203 | m_ampEnv.GateOff(); 204 | m_shaperEnv.GateOff(); 205 | } 206 | 207 | void Voice::PitchBend(float value) 208 | { 209 | m_bend = value; 210 | CalcPitch(); 211 | } 212 | 213 | void Voice::CalcPitch() 214 | { 215 | float pitch; 216 | float pitch2; 217 | 218 | if (m_bend < 0) 219 | { 220 | pitch = m_delta + ((m_delta-m_deltaLo)*m_bend); 221 | pitch2 = m_delta2 + ((m_delta2-m_deltaLo2)*m_bend); 222 | } 223 | else 224 | { 225 | pitch = m_delta + ((m_deltaHi-m_delta)*m_bend); 226 | pitch2 = m_delta2 + ((m_deltaHi2-m_delta2)*m_bend); 227 | } 228 | 229 | pitch = (1.0f-m_deltaBlend)*pitch + (m_deltaBlend)*pitch2; 230 | 231 | m_pdOsc2.SetPitch((pitch) - (pitch*m_detune)); 232 | m_pdOsc1.SetPitch((pitch * m_octave) + (pitch * m_detune)); 233 | m_resoGen.SetPitch(pitch); 234 | } 235 | 236 | void Voice::SetBasisWaves() 237 | { 238 | m_pdOsc1.SetBasis(m_basisWave); 239 | m_pdOsc2.SetBasis(m_basisWave); 240 | 241 | } 242 | 243 | void Voice::SetPulseWidths() 244 | { 245 | m_pdOsc1.SetPulseWidth(m_pulseWidth); 246 | m_pdOsc2.SetPulseWidth(m_pulseWidth); 247 | m_resoGen.SetPulseWidth(m_pulseWidth); 248 | } 249 | 250 | void Voice::Render(float *out, int len, Voice::voiceBuffers_t* bufs, bool doContourGens, int thread) 251 | { 252 | // If the mutex is busy, it means another thread has already grabbed 253 | // this voice and its subvoices, so skip it 254 | #ifdef DIGITS_MULTICORE 255 | if (pthread_mutex_trylock(&m_mutex) == EBUSY) 256 | { 257 | DEBUG_MCORE("%s: Lock was busy on voice %d\n", thread==0? "c" : "h", m_voiceNumber); 258 | Tables::ZeroMem(out, len); 259 | return; 260 | } 261 | #endif 262 | 263 | if (IsFree() || !m_needsRender) 264 | { 265 | Tables::ZeroMem(out, len); 266 | #ifdef DIGITS_MULTICORE 267 | pthread_mutex_unlock(&m_mutex); 268 | #endif 269 | m_needsRender = false; 270 | return; 271 | } 272 | 273 | DEBUG_MCORE("%s: processing voice %d\n", thread==0? "c": "h", m_voiceNumber); 274 | m_needsRender = false; 275 | 276 | // Initialize buffers (previously InitBuffers, pre-multicore) 277 | m_pdOsc1.SetBuffers(bufs->m_ampEnvBuf, bufs->m_shpEnvBuf, bufs->m_lfoBufs); 278 | m_pdOsc2.SetBuffers(bufs->m_ampEnvBuf, bufs->m_shpEnvBuf, bufs->m_lfoBufs); 279 | m_resoGen.SetBuffers(bufs->m_ampEnvBuf, bufs->m_shpEnvBuf, bufs->m_lfoBufs); 280 | 281 | // Lock (or unlock) shaper to the specified setting. 0 is off. 282 | m_pdOsc1.LockShaperTo(m_lockShaperAmt); 283 | m_pdOsc2.LockShaperTo(m_lockShaperAmt); 284 | 285 | if (doContourGens) 286 | { 287 | float shpMod = (1.0f-m_velocity) * m_velShp; 288 | 289 | // TODO: Do we want to just set ctlAmt to this? Maybe. Might be more consistent. 290 | m_shaperEnv.SetMaximum(m_shpMax - m_shpMax*shpMod); 291 | m_shaperEnv.SetMinimum(m_shpMin - m_shpMin*shpMod); 292 | 293 | float ctlAmt = m_modWheel*m_modShp + m_aftertouch*m_atouchShp; 294 | if (ctlAmt > 1.0f) 295 | ctlAmt = 1.0f; 296 | m_shaperEnv.SetControlInput(1.0f-ctlAmt); 297 | 298 | m_shaperEnv.Render(bufs->m_shpEnvBuf->Data(), len); 299 | m_ampEnv.Render(bufs->m_ampEnvBuf->Data(), len); 300 | 301 | // TODO: LFOs are surprisingly costly, so we should only 302 | // render this if the LFO is assigned. This should be determined 303 | // when the LFO levels are adjusted, not determined each frame! 304 | for (int i=0; im_lfoBufs[i]->Data(), len); 308 | } 309 | 310 | // Apply LFO1 attenuation if enabled 311 | // TODO: vDSP this sucker! 312 | if (m_atouchLFO1Amp || m_modLFO1Amp) 313 | { 314 | float influence = (1.0f-m_aftertouch)*m_atouchLFO1Amp + (1.0f-m_modWheel)*m_modLFO1Amp; 315 | for (int i=0; im_lfoBufs[0]->Data()[i] *= 1.0f - influence; 317 | } 318 | } 319 | //... but the noise LFO is rendered regardless 320 | else 321 | { 322 | for (int i=0; im_lfoBufs[i]->Data(), len); 326 | } 327 | } 328 | 329 | // Animate glide 330 | if (m_deltaBlend > 0) 331 | { 332 | CalcPitch(); 333 | m_deltaBlend += 1.0f / m_glideSpeed; 334 | if (m_deltaBlend >= 1.0f) 335 | { 336 | m_deltaBlend = 0; 337 | m_delta = m_delta2; 338 | m_deltaHi = m_deltaHi2; 339 | m_deltaLo = m_deltaLo2; 340 | CalcPitch(); 341 | } 342 | } 343 | 344 | // If doContourGens is false, we assume it's because we're rendering a subvoice 345 | if (doContourGens) 346 | Tables::ZeroMem(out, len); 347 | 348 | float pdVol = 1.0f - m_resoVol; 349 | if (pdVol > 0) 350 | { 351 | Tables::ZeroMem(bufs->m_fmScratchBuf->Data(), len); 352 | 353 | // Don't add in the volume here because it affects the FM indexing 354 | m_pdOsc1.Render(0, bufs->m_fmScratchBuf->Data(), len, 1.0f); 355 | m_pdOsc2.Render(bufs->m_fmScratchBuf->Data(), out, len, m_mix); 356 | 357 | // Scale the volume afterwards so it doesn't interfere with 358 | // the FM indexing, and also apply the envelope here since it's 359 | // a unified envelope for both oscillators 360 | // TODO: Fold this into the volume specified in the pdOsc render function 361 | // and save a mul 362 | // TODO: vDSP this stuff 363 | float osc1mix = 1.0f - m_mix; 364 | for (int i=0; im_fmScratchBuf->Data()[i] * osc1mix; 367 | out[i] *= pdVol * bufs->m_ampEnvBuf->Data()[i]; 368 | } 369 | } 370 | if (pdVol < 1.0f) 371 | { 372 | m_resoGen.Render(out, len, m_resoVol); 373 | } 374 | 375 | // Render the subvoices (without contour generator) 376 | if (m_nextSubVoice) 377 | { 378 | if (m_ampEnv.IsDone()) 379 | m_nextSubVoice->DisableSubVoices(); 380 | m_nextSubVoice->Render(out, len, bufs, false, thread); 381 | } 382 | 383 | // TODO: Find a way to unify volumes so this can be done in the loop above 384 | // TODO: Or at least do this only once for all subvoices 385 | if (doContourGens) 386 | { 387 | // If shaper is locked, that means the filter is engaged (and is responsible 388 | // for brightness control) 389 | if (m_lockShaperAmt) 390 | { 391 | m_trueFilter.SetFrequency(18000.0f * bufs->m_shpEnvBuf->Data()[0]); 392 | m_trueFilter.Render(out, len); 393 | } 394 | 395 | for (int i=0; im_lfoBufs[0]->Data()[i]*m_lfoAmplitude[0] 399 | + bufs->m_lfoBufs[1]->Data()[i]*m_lfoAmplitude[1] 400 | + bufs->m_lfoBufs[2]->Data()[i]*m_lfoAmplitude[2]; 401 | #else 402 | float lfoInfluence = bufs->m_lfoBufs[0]->Data()[i]*m_lfoAmplitude[0]; 403 | #endif 404 | out[i] -= (out[i]*lfoInfluence); 405 | } 406 | } 407 | 408 | if (m_bitCrushBlend) 409 | { 410 | for (int i=0; i < len; i++) 411 | { 412 | m_bitCrushPos += m_bitCrushDelta; 413 | if (m_bitCrushPos >= 1.0f) 414 | { 415 | m_bitCrushLastSample = (int)(out[i] * m_bitCrushBits); 416 | m_bitCrushPos -= 1.0f; 417 | } 418 | out[i] = ((float)m_bitCrushLastSample / (float)m_bitCrushBits)*m_bitCrushBlend + out[i]*(1.0-m_bitCrushBlend); 419 | } 420 | } 421 | 422 | #ifdef DIGITS_MULTICORE 423 | pthread_mutex_unlock(&m_mutex); 424 | #endif 425 | } 426 | 427 | void Voice::SetParameter(int index, float value) 428 | { 429 | // Obtain Mutex 430 | 431 | VstCore::paramNums_t num = (VstCore::paramNums_t)index; 432 | int lfoSelect = -1; 433 | 434 | switch(num) 435 | { 436 | case VstCore::kO1Skew: 437 | m_pdOsc1.SetSkew(.5f + (value * .5f)); 438 | break; 439 | case VstCore::kO1ShpMod: 440 | { 441 | float val; 442 | if (value < .25) 443 | val = .5f; 444 | else if (value < .5) 445 | val = 1.0f; 446 | else if (value < .75) 447 | val = 2.0f; 448 | else 449 | val = 3.0f; 450 | m_pdOsc1.SetShaperMod(val); 451 | break; 452 | } 453 | case VstCore::kO2Skew: 454 | m_pdOsc2.SetSkew(.5f + (value * .5f)); 455 | break; 456 | case VstCore::kO2ShpMod: 457 | { 458 | float val; 459 | if (value < .25) 460 | val = .5f; 461 | else if (value < .5) 462 | val = 1.0f; 463 | else if (value < .75) 464 | val = 2.0f; 465 | else 466 | val = 3.0f; 467 | m_pdOsc2.SetShaperMod(val); 468 | break; 469 | } 470 | case VstCore::kO2Vol: 471 | m_mix = value; 472 | break; 473 | case VstCore::kResoVol: 474 | m_resoVol = value; 475 | break; 476 | case VstCore::kResoWave: 477 | if (value < .25) 478 | m_resoGen.SetStyle(ResoGen::kSawQuarter); 479 | else if (value < .5) 480 | m_resoGen.SetStyle(ResoGen::kSawHalf); 481 | else if (value < .75) 482 | m_resoGen.SetStyle(ResoGen::kSquareQuarter); 483 | else 484 | m_resoGen.SetStyle(ResoGen::kSquareHalf); 485 | break; 486 | case VstCore::kAmpAtt: 487 | m_ampAttack = value * kAttackRange + kAttackMinimumAmp; 488 | m_ampEnv.SetAttackExponential(m_ampAttack, m_sR); 489 | break; 490 | case VstCore::kAmpDec: 491 | m_ampDecay = value * kDecayRange + kDecayMinimum; 492 | m_ampEnv.SetDecayExponential(m_ampDecay, m_sR); 493 | break; 494 | case VstCore::kAmpRel: 495 | m_ampRelease = value * kReleaseRange + kReleaseMinimum; 496 | m_ampEnv.SetReleaseExponential(m_ampRelease, m_sR); 497 | break; 498 | case VstCore::kAmpSus: 499 | m_ampEnv.SetSustainLevel(value); 500 | break; 501 | case VstCore::kAmpFade: 502 | if (value == 1.0f) 503 | m_ampEnv.SetFadeDirect(1.0f); 504 | else if (value > 0) 505 | m_ampEnv.SetFadeExponential(value * kFadeRange + kFadeMinimum, m_sR); 506 | else 507 | m_ampEnv.SetFadeDirect(0); 508 | break; 509 | case VstCore::kShpAtt: 510 | m_shpAttack = value * kAttackRange + kAttackMinimumShaper; 511 | m_shaperEnv.SetAttackExponential(m_shpAttack, m_sR); 512 | break; 513 | case VstCore::kShpDec: 514 | m_shpDecay = value * kDecayRange + kDecayMinimum; 515 | m_shaperEnv.SetDecayExponential(m_shpDecay, m_sR); 516 | break; 517 | case VstCore::kShpRel: 518 | m_shpRelease = value * kReleaseRange + kReleaseMinimum; 519 | m_shaperEnv.SetReleaseExponential(m_shpRelease, m_sR); 520 | break; 521 | case VstCore::kShpSus: 522 | m_shaperEnv.SetSustainLevel(value); 523 | break; 524 | case VstCore::kShpFade: 525 | if (value == 1.0f) 526 | m_shaperEnv.SetFadeDirect(1.0); 527 | else if (value > 0) 528 | m_shaperEnv.SetFadeExponential(1.0f * kFadeRange + kFadeMinimum, m_sR); 529 | else 530 | m_shaperEnv.SetFadeDirect(0); 531 | break; 532 | case VstCore::kShpMin: 533 | // TODO: Shouldn't these be in the envelope section? 534 | if (value == 0) 535 | { 536 | m_shaperEnv.NoAttack(); 537 | } 538 | else 539 | { 540 | m_shaperEnv.NoAttack(false); 541 | // m_shaperEnv.SetMinimum(value); 542 | } 543 | 544 | m_shpMin = value; 545 | break; 546 | case VstCore::kShpMax: 547 | m_shpMax = value; 548 | break; 549 | case VstCore::kFM: 550 | m_pdOsc2.SetFMInputAmt(4.0f * value); 551 | break; 552 | case VstCore::kDetune: 553 | m_detune = value * kDetuneMaximum; 554 | break; 555 | case VstCore::kOctave: { 556 | int oct = (int)(value*6.0f) - 1; 557 | m_octave = pow((float)2, (float)oct); 558 | /* 559 | if (value < .25) 560 | m_octave = .5; 561 | else if (value < .5) 562 | m_octave = 1.0; 563 | else if (value < .75) 564 | m_octave = 2.0; 565 | else 566 | m_octave = 4.0;*/ 567 | } 568 | break; 569 | case VstCore::kBasisWave: 570 | m_basisWave = value < .5? 0 : 1; 571 | SetBasisWaves(); 572 | break; 573 | case VstCore::kPulseWidth: 574 | m_pulseWidth = kPWMMinimum + (value * kPWMRange); 575 | SetPulseWidths(); 576 | break; 577 | case VstCore::kVelShaper: 578 | SetVelocityShp(value); 579 | break; 580 | case VstCore::kVelVolume: 581 | SetVelocityAmp(value); 582 | break; 583 | case VstCore::kLFORate: 584 | if (lfoSelect == -1) lfoSelect = 0; 585 | #ifdef DIGITS_PRO 586 | case VstCore::kLFO2Rate: 587 | if (lfoSelect == -1) lfoSelect = 1; 588 | case VstCore::kLFO3Rate: 589 | if (lfoSelect == -1) lfoSelect = 2; 590 | #endif 591 | value = ExpShape(100.0f, value); 592 | m_lfos[lfoSelect].SetRate(kLFOMinimum + (value * kLFORange), m_sR); 593 | break; 594 | case VstCore::kLFOType: 595 | if (lfoSelect == -1) lfoSelect = 0; 596 | #ifdef DIGITS_PRO 597 | case VstCore::kLFO2Type: 598 | if (lfoSelect == -1) lfoSelect = 1; 599 | case VstCore::kLFO3Type: 600 | if (lfoSelect == -1) lfoSelect = 2; 601 | #endif 602 | if (value < .25) 603 | m_lfos[lfoSelect].SetType(LFO::kLFO_Sin); 604 | else if (value < .5) 605 | m_lfos[lfoSelect].SetType(LFO::kLFO_Noise); 606 | else if (value < .75) 607 | m_lfos[lfoSelect].SetType(LFO::kLFO_RampDn); 608 | else 609 | m_lfos[lfoSelect].SetType(LFO::kLFO_RampUp); 610 | break; 611 | case VstCore::kLFODelay: 612 | if (lfoSelect == -1) lfoSelect = 0; 613 | #ifdef DIGITS_PRO 614 | case VstCore::kLFO2Delay: 615 | if (lfoSelect == -1) lfoSelect = 1; 616 | case VstCore::kLFO3Delay: 617 | if (lfoSelect == -1) lfoSelect = 2; 618 | #endif 619 | // Up to two seconds 620 | m_lfos[lfoSelect].SetDelay(value * 2000.0f, m_sR); 621 | break; 622 | case VstCore::kLFORepeat: 623 | if (lfoSelect == -1) lfoSelect = 0; 624 | #ifdef DIGITS_PRO 625 | case VstCore::kLFO2Repeat: 626 | if (lfoSelect == -1) lfoSelect = 1; 627 | case VstCore::kLFO3Repeat: 628 | if (lfoSelect == -1) lfoSelect = 2; 629 | #endif 630 | if (value == 1.0f) 631 | m_lfos[lfoSelect].SetRepeat(-1); 632 | else 633 | m_lfos[lfoSelect].SetRepeat(1+(value*4)); 634 | break; 635 | case VstCore::kLFOShp: 636 | if (lfoSelect == -1) lfoSelect = 0; 637 | #ifdef DIGITS_PRO 638 | case VstCore::kLFO2Shp: 639 | if (lfoSelect == -1) lfoSelect = 1; 640 | case VstCore::kLFO3Shp: 641 | if (lfoSelect == -1) lfoSelect = 2; 642 | #endif 643 | m_pdOsc1.SetLFOShaper(lfoSelect, value); 644 | m_pdOsc2.SetLFOShaper(lfoSelect, value); 645 | m_resoGen.SetLFOShaper(lfoSelect, value); 646 | if (value > 0) 647 | m_lfoIsAssigned[lfoSelect] |= kLFOa_toShaper; 648 | else 649 | m_lfoIsAssigned[lfoSelect] &= ~kLFOa_toShaper; 650 | break; 651 | case VstCore::kLFOAmp: 652 | if (lfoSelect == -1) lfoSelect = 0; 653 | #ifdef DIGITS_PRO 654 | case VstCore::kLFO2Amp: 655 | if (lfoSelect == -1) lfoSelect = 1; 656 | case VstCore::kLFO3Amp: 657 | if (lfoSelect == -1) lfoSelect = 2; 658 | #endif 659 | m_lfoAmplitude[lfoSelect] = value; 660 | if (value > 0) 661 | m_lfoIsAssigned[lfoSelect] |= kLFOa_toAmp; 662 | else 663 | m_lfoIsAssigned[lfoSelect] &= ~kLFOa_toAmp; 664 | 665 | break; 666 | case VstCore::kLFOFrq: 667 | if (lfoSelect == -1) lfoSelect = 0; 668 | #ifdef DIGITS_PRO 669 | case VstCore::kLFO2Frq: 670 | if (lfoSelect == -1) lfoSelect = 1; 671 | case VstCore::kLFO3Frq: 672 | if (lfoSelect == -1) lfoSelect = 2; 673 | #endif 674 | m_pdOsc1.SetLFOPitch(lfoSelect, value * .75f); 675 | m_pdOsc2.SetLFOPitch(lfoSelect, value * .75f); 676 | m_resoGen.SetLFOPitch(lfoSelect, value); 677 | if (value > 0) 678 | m_lfoIsAssigned[lfoSelect] |= kLFOa_toPitch; 679 | else 680 | m_lfoIsAssigned[lfoSelect] &= ~kLFOa_toPitch; 681 | break; 682 | case VstCore::kLFOPWM: 683 | if (lfoSelect == -1) lfoSelect = 0; 684 | #ifdef DIGITS_PRO 685 | case VstCore::kLFO2PWM: 686 | if (lfoSelect == -1) lfoSelect = 1; 687 | case VstCore::kLFO3PWM: 688 | if (lfoSelect == -1) lfoSelect = 2; 689 | #endif 690 | m_pdOsc1.SetLFOPWM(lfoSelect, value); 691 | m_pdOsc2.SetLFOPWM(lfoSelect, value); 692 | m_resoGen.SetLFOPWM(lfoSelect, value); 693 | if (value > 0) 694 | m_lfoIsAssigned[lfoSelect] |= kLFOa_toPWM; 695 | else 696 | m_lfoIsAssigned[lfoSelect] &= ~kLFOa_toPWM; 697 | 698 | break; 699 | #if DIGITS_PRO 700 | case VstCore::kLockShaperForFilter: 701 | m_lockShaperAmt = value; 702 | break; 703 | case VstCore::kFilterReso: 704 | // fudge factor for higher sampling rates-- dermined by ear 705 | if (m_sR >= 88200) 706 | value *= .93f; 707 | m_trueFilter.SetSharpness(3.5f * value); 708 | break; 709 | case VstCore::kFilterMode: 710 | if (value < .25) 711 | m_trueFilter.SetPoles(4); 712 | else if (value < .5) 713 | m_trueFilter.SetPoles(3); 714 | else if (value < .75) 715 | m_trueFilter.SetPoles(2); 716 | else 717 | m_trueFilter.SetPoles(1); 718 | break; 719 | case VstCore::kMonoMode: 720 | if (value < .25) 721 | m_glideMode = kGlide_PolyNoGlide; 722 | else if (value < .5) 723 | m_glideMode = kGlide_PolyGlideAlways; 724 | else if (value < .75) 725 | m_glideMode = kGlide_MonoGlideWhenHeld; 726 | else 727 | m_glideMode = kGlide_MonoGlideAlways; 728 | break; 729 | case VstCore::kPortaSpeed: 730 | if (value == 0) 731 | m_glideSpeed = 1.0f; 732 | else 733 | m_glideSpeed = value * 500.0f; 734 | break; 735 | #endif 736 | case VstCore::kModShaper: 737 | SetModWheelShaper(value); 738 | break; 739 | case VstCore::kModLFO1Amp: 740 | SetModWheelLFO1Amp(value); 741 | break; 742 | case VstCore::kAftertouchShaper: 743 | SetAftertouchShaper(value); 744 | break; 745 | case VstCore::kAftertouchLFO1Amp: 746 | SetAftertouchLFO1Amp(value); 747 | break; 748 | #if DIGITS_PRO 749 | case VstCore::kAmpRateScale: 750 | m_ampRateScale = value; 751 | break; 752 | case VstCore::kShpRateScale: 753 | m_shpRateScale = value; 754 | break; 755 | case VstCore::kShpLevelScale: 756 | m_shpLevelScale = value * .25f; 757 | break; 758 | case VstCore::kBitDiv: 759 | m_bitCrushPos = 0; 760 | m_bitCrushDivider = floor(value * 9.0f) + 1.0; 761 | break; 762 | case VstCore::kBitBit: 763 | m_bitCrushPos = 0; 764 | m_bitCrushBits = floor(value * 14.0f) + 2.0; 765 | break; 766 | case VstCore::kBitBlend: 767 | m_bitCrushBlend = value; 768 | break; 769 | #endif 770 | default: 771 | break; 772 | } 773 | } 774 | 775 | void Voice::InitiateGlide(float delta, float deltaHi, float deltaLo) 776 | { 777 | float unblend = 1.0f - m_deltaBlend; 778 | 779 | m_delta = m_delta*unblend + m_delta2*m_deltaBlend; 780 | m_deltaHi = m_deltaHi*unblend + m_deltaHi2*m_deltaBlend; 781 | m_deltaLo = m_deltaLo*unblend + m_deltaLo2*m_deltaBlend; 782 | 783 | m_delta2 = delta; 784 | m_deltaHi2 = deltaHi; 785 | m_deltaLo2 = deltaLo; 786 | m_deltaBlend = .001f; // Turn it on 787 | } 788 | 789 | -------------------------------------------------------------------------------- /src/components/Voice.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #ifndef _VOICE_H_ 4 | #define _VOICE_H_ 5 | 6 | #include 7 | #include "SndBuf.h" 8 | #include "PhaseDist.h" 9 | #include "ResoGen.h" 10 | #include "Contour.h" 11 | #include "FilterBank.h" 12 | #include "LFO.h" 13 | 14 | class Voice 15 | { 16 | public: 17 | struct voiceBuffers_t 18 | { 19 | SndBuf* m_voiceBuf; 20 | SndBuf* m_shpEnvBuf; 21 | SndBuf* m_ampEnvBuf; 22 | SndBuf* m_lfoBufs[Tables::kNumLFOs]; 23 | SndBuf* m_fmScratchBuf; 24 | }; 25 | 26 | // These probably could be moved to VstCore 27 | static float kAttackMinimumAmp; 28 | static float kAttackMinimumShaper; 29 | static float kAttackRange; 30 | static float kFadeMinimum; 31 | static float kFadeRange; 32 | static float kReleaseMinimum; 33 | static float kReleaseRange; 34 | static float kDecayMinimum; 35 | static float kDecayRange; 36 | static float kDetuneMaximum; 37 | static float kLFOMinimum; 38 | static float kLFORange; 39 | static float kPWMMinimum; 40 | static float kPWMRange; 41 | 42 | // voiceNumber = the number of the voice this is (for debug purposes) 43 | Voice(int voiceNumber); 44 | ~Voice(); 45 | 46 | // Set doContourGen to false when rendering as a subvoice 47 | // Buffers must be passed in at render-time because multicore support needs separate buffers for each 48 | // helper thread 49 | // doContourGens is true if the contour generators are supposed to be renderd. False if we're intentionally 50 | // rendering a subvoice. 51 | // debugthread is the number of the thread (0=core, 1=helper 1, 2=helper 2, etc) for debug purposes 52 | void Render(float *out, int len, Voice::voiceBuffers_t* bufs, bool doContourGens, int debugthread); 53 | // BUFFER SET IS FOR: fmIn, SndBuf *shaperBuf, SndBuf *ampBuf, SndBuf **lfoBufs, bool doContourGens); 54 | void NoteOn(uint64_t timestamp, float deltaLo, float deltaHi, float delta, int midiKey, int velocity, bool reset=true); 55 | // Pass in a negative value to turn the note off regardless of pitch 56 | void NoteOff(int key); 57 | // Pass in -1.0 to 1.0 58 | void PitchBend(float value); 59 | // Pass in 0 to 1.0 60 | void SetModWheel(float value) { m_modWheel = value; } 61 | // Pass in 0 to 1.0 62 | void SetAftertouch(float value) { m_aftertouch = value; } 63 | // Notify the Voice of the current sampling rate 64 | void SetSamplingRate(float sR) { m_sR = sR; } 65 | 66 | void ResetPhases() 67 | { 68 | m_resoGen.ResetPhase(); 69 | m_pdOsc1.ResetPhase(); 70 | m_pdOsc2.ResetPhase(); 71 | } 72 | 73 | // Return true if this voice can be stolen 74 | // or reused 75 | bool IsFree() 76 | { 77 | return m_ampEnv.IsDone(); 78 | } 79 | bool IsReleased() { return m_ampEnv.IsReleased(); } 80 | int Pitch() { return m_pitch; } 81 | void SetParameter(int index, float value); 82 | inline float Clip(float x); 83 | uint64_t GetTimestamp() { return m_timestamp; } 84 | 85 | void InitiateGlide(float delta, float deltaHi, float deltaLo); 86 | 87 | // Set ties between velocity and amplitude/shaper 88 | void SetVelocityAmp(float amt) { m_velAmp = amt; } 89 | void SetVelocityShp(float amt) { m_velShp = amt; } 90 | 91 | void SetPulseWidths(); 92 | void SetBasisWaves(); 93 | 94 | // At the beginning of buffer processing, these are all true. As voices are rendered, 95 | // needsRender is set to false. 96 | bool NeedsRender() { return m_needsRender; } 97 | // In multicore mode, make sure this is wrapped in a mutex. It's not individually 98 | // wrapped because that's wasteful, kinda like individually-wrapped M&Ms. 99 | void SetNeedsRender(bool needsRender=true) 100 | { 101 | m_needsRender = needsRender; 102 | } 103 | void SetIsSubVoice(bool isSubVoice) { m_isSubVoice = isSubVoice; } 104 | bool IsSubVoice() { return m_isSubVoice; } 105 | 106 | // Set the subvoice pointer (for optimization of orch/phat/unison mode) 107 | void SetNextSubVoice(Voice* nextSubVoice) 108 | { 109 | fprintf(stderr, "SetNextSubVoice %p -> %p\n", this, nextSubVoice); 110 | m_nextSubVoice = nextSubVoice; 111 | if (nextSubVoice) 112 | nextSubVoice->SetIsSubVoice(true); 113 | } 114 | 115 | // Recursively go through the subvoice list and turn off all the envelopes (disable voice) 116 | void DisableSubVoices() 117 | { 118 | m_ampEnv.SetDone(); 119 | if (m_nextSubVoice) 120 | m_nextSubVoice->DisableSubVoices(); 121 | } 122 | 123 | // When we engage the filter, we lock the shaper at a 124 | // specific value. This is the amount it's locked to. 125 | void LockShaperTo(float val) { m_lockShaperAmt = val; } 126 | 127 | void UpdateFilterSamplingRate(float sR) { m_trueFilter.SetSamplingRate(sR); } 128 | 129 | // Set influence for aftertouch and modwheel 130 | void SetAftertouchShaper(float value) { m_atouchShp = value; } 131 | void SetAftertouchLFO1Amp(float value) { m_atouchLFO1Amp = value; } 132 | void SetModWheelShaper(float value) { m_modShp = value; } 133 | void SetModWheelLFO1Amp(float value) { m_modLFO1Amp = value; } 134 | 135 | bool ShaperLocked() { return (m_lockShaperAmt > 0); } 136 | 137 | // Divider should be in the range of 1 to 8, or 0 for off. 138 | // void SetBitCrushDivider(float div) { m_bitCrushDivider = div; } 139 | // void SetBitCrushBits(int bits) { m_bitCrushBits = pow(2, bits); } 140 | 141 | private: 142 | #ifdef DIGITS_MULTICORE 143 | // Mutex is locked when setParameter 144 | pthread_mutex_t m_mutex; 145 | #endif 146 | 147 | enum GlideMode 148 | { 149 | kGlide_PolyNoGlide, 150 | kGlide_PolyGlideAlways, 151 | kGlide_MonoGlideWhenHeld, 152 | kGlide_MonoGlideAlways 153 | }; 154 | 155 | uint64_t m_timestamp; 156 | 157 | Contour m_ampEnv; 158 | Contour m_shaperEnv; 159 | PhaseDist m_pdOsc1; 160 | PhaseDist m_pdOsc2; 161 | LFO m_lfos[Tables::kNumLFOs]; 162 | 163 | ResoGen m_resoGen; 164 | // MIDI pitch value used for note on/offs 165 | int m_pitch; 166 | float m_detune; 167 | float m_octave; 168 | float m_mix; 169 | float m_resoVol; 170 | float m_pulseWidth; 171 | float m_lfoAmplitude[Tables::kNumLFOs]; // How much LFO affects the amplitude 172 | 173 | // Pitch delta 174 | float m_delta; 175 | // Pitch bend down delta 176 | float m_deltaLo; 177 | // Pitch bend up delta 178 | float m_deltaHi; 179 | 180 | // The same, but for notes that we're sliding to (monophonic mode) 181 | float m_delta2; 182 | float m_deltaLo2; 183 | float m_deltaHi2; 184 | // The position from 0 to 1 between the two pitches we're at 185 | float m_deltaBlend; 186 | // How long it takes for a portamento (glide) to finish. This is in terms of control 187 | // rate frames. At the time of writing, the control rate is 1000/sec, so milliseconds. 188 | float m_glideSpeed; 189 | // The glide mode 190 | GlideMode m_glideMode; 191 | 192 | // Last pitch wheel value 193 | float m_bend; 194 | // Last mod wheel value 195 | float m_modWheel; 196 | // Last aftertouch value 197 | float m_aftertouch; 198 | // Velocity 199 | float m_velocity; 200 | 201 | int m_basisWave; // 0 = cos, 1 = sin 202 | 203 | // These are stored here because we want to set these per 204 | // note (for tying velocity to brightness) 205 | float m_shpMin; 206 | float m_shpMax; 207 | float m_velShp; 208 | float m_velAmp; 209 | 210 | float m_modShp; 211 | float m_modLFO1Amp; 212 | float m_atouchShp; 213 | float m_atouchLFO1Amp; 214 | 215 | // Calculate pitch based on frequency deltas and pitch wheel value 216 | void CalcPitch(); 217 | // Recalculate envelopes (for sample rate changes) 218 | void RecalcEnvs() {} // TODO 219 | 220 | // Set to null when there's no more subvoices 221 | Voice *m_nextSubVoice; 222 | // This is so that the main render loop doesn't end up 223 | // rendering this voice twice (if it's a subvoice) 224 | bool m_needsRender; 225 | // This is a sub-voice (phat/unison/orch mode) 226 | bool m_isSubVoice; 227 | 228 | LowPassReso m_trueFilter; 229 | // When we engage the filter, we lock the shaper at a 230 | // specific value. This is the amount it's locked to. 231 | float m_lockShaperAmt; 232 | 233 | // Current sampling rate 234 | float m_sR; 235 | 236 | // The number of the voice for debugging purposes 237 | int m_voiceNumber; 238 | 239 | // Bitfield that shows the LFO assignments. When it's 0, it's 240 | // safe not to process that LFO 241 | static const int kLFOa_toShaper = 1; 242 | static const int kLFOa_toPWM = 2; 243 | static const int kLFOa_toAmp = 3; 244 | static const int kLFOa_toPitch = 4; 245 | int m_lfoIsAssigned[Tables::kNumLFOs]; 246 | 247 | // Envelope settings, for rate/level scaling upon note-on 248 | // Rate and level scaling, in terms of 249 | // speedup or attenuation per octave. Ramps 250 | // based on frequency. e.g., .5 for level would 251 | // attenuate the envelope by .5 per octave. 2 for 252 | // rate would double the envelope speed each octave, 253 | // starting at 60hz. 254 | float m_ampRateScale; 255 | float m_ampLevelScale; 256 | float m_ampAttack; 257 | float m_ampDecay; 258 | float m_ampRelease; 259 | float m_shpRateScale; 260 | float m_shpLevelScale; 261 | float m_shpAttack; 262 | float m_shpDecay; 263 | float m_shpRelease; 264 | 265 | // Sample-hold for the smart bitcrush 266 | float m_bitCrushPos; 267 | float m_bitCrushDelta; 268 | int m_bitCrushLastSample; 269 | float m_bitCrushBlend; 270 | float m_bitCrushDivider; 271 | int m_bitCrushBits; 272 | }; 273 | 274 | #endif 275 | 276 | -------------------------------------------------------------------------------- /src/digits/DigitsBench.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * DigitsBench.cpp 3 | * PDVST 4 | * 5 | * Created by Louis Gorenfeld on 9/20/12. 6 | * Copyright 2012 ExtentOfTheJam. All rights reserved. 7 | * 8 | * This is a minimal class to provide a decent benchmark for 9 | * Digits outside of the host 10 | */ 11 | 12 | #include "VstCore.h" 13 | 14 | int main() 15 | { 16 | static const int kBlockSize = 256; 17 | VstCore digitsCore((void*)1); 18 | 19 | digitsCore.setSampleRate(48000); 20 | digitsCore.setBlockSize(kBlockSize); 21 | digitsCore.setProgram(3 /* Flanger strings */); 22 | 23 | 24 | VstEvents *ev = (VstEvents*)new char[sizeof(VstEvents) + 2*sizeof(VstMidiEvent*)]; 25 | VstMidiEvent midiEvents[4]; 26 | midiEvents[0].midiData[0] = 0x90; 27 | midiEvents[0].midiData[1] = 64; 28 | midiEvents[0].midiData[2] = 0x7f; 29 | midiEvents[0].deltaFrames = 0; 30 | midiEvents[1].midiData[0] = 0x90; 31 | midiEvents[1].midiData[1] = 66; 32 | midiEvents[1].midiData[2] = 0x7f; 33 | midiEvents[1].deltaFrames = 0; 34 | midiEvents[2].midiData[0] = 0x90; 35 | midiEvents[2].midiData[1] = 68; 36 | midiEvents[2].midiData[2] = 0x7f; 37 | midiEvents[2].deltaFrames = 0; 38 | midiEvents[3].midiData[0] = 0x90; 39 | midiEvents[3].midiData[1] = 70; 40 | midiEvents[3].midiData[2] = 0x7f; 41 | midiEvents[3].deltaFrames = 0; 42 | 43 | ev->events[0] = &midiEvents[0]; 44 | ev->events[1] = &midiEvents[1]; 45 | ev->events[2] = &midiEvents[2]; 46 | ev->events[3] = &midiEvents[3]; 47 | ev->numEvents = 4; 48 | 49 | digitsCore.processEvents(ev); 50 | /* 51 | FILE *fp = fopen("DigitsBench.raw", "wb"); 52 | float *outs[2]; 53 | outs[0] = new float[48000]; 54 | outs[1] = new float[48000]; 55 | digitsCore.processReplacing(0, outs, 48000); 56 | 57 | fwrite(outs[0], sizeof(float), 48000, fp); 58 | 59 | fclose(fp); 60 | */ 61 | 62 | float *outs[2]; 63 | outs[0] = new float[kBlockSize]; 64 | outs[1] = new float[kBlockSize]; 65 | 66 | // Render 1 minute of audio at 48khz 67 | for (int i=0; i<(48000*60)/256; i++) 68 | { 69 | digitsCore.processReplacing(0, outs, kBlockSize); 70 | } 71 | 72 | delete[] outs[0]; 73 | delete[] outs[1]; 74 | 75 | return 0; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/digits/EditorWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EditorWindow.h 3 | * PDVST 4 | * 5 | * Created by Louis Gorenfeld on 7/29/12. 6 | * Copyright 2012 ExtentOfTheJam. All rights reserved. 7 | * 8 | */ 9 | 10 | #ifndef _EDITWINDOW_H_ 11 | #define _EDITWINDOW_H_ 12 | 13 | #include "../vstgui/plugin-bindings/aeffguieditor.h" 14 | #include "VstCore.h" // kNumParameters 15 | 16 | class EditorWindow : public AEffGUIEditor, public IControlListener 17 | { 18 | public: 19 | EditorWindow(void *p); 20 | ~EditorWindow(); 21 | 22 | // AEffGUIEditor 23 | virtual bool open (void* ptr); 24 | void close (); 25 | void setParameter (VstInt32 index, float value); 26 | void idle(); 27 | 28 | // CControlListener 29 | void valueChanged (CControl* pControl); 30 | 31 | // The guts of the effect 32 | VstCore *m_me; 33 | 34 | protected: 35 | enum oscType_t 36 | { 37 | kOsc1, 38 | kOsc2, 39 | kReso 40 | }; 41 | 42 | enum tripleType_t 43 | { 44 | kMix, 45 | kAmpEnv, 46 | kShpEnv 47 | }; 48 | 49 | static const int kEditorWidth = 890; 50 | static const int kEditorHeight = 440; 51 | // Padding between the edge of a panel and the first 52 | // control (e.g., from left side of panel to first control) 53 | static const int kSidePadding = 20; 54 | static const int kDialPadding = 50; 55 | static const int kDialWidth = 32; 56 | static const int kDialSpacing = kDialWidth + 16; 57 | 58 | // How far beneath the dial is the text? 59 | static const int kDialTextPadding = 0; 60 | // Position text 10 pixels beneath dial 61 | static const int kTextPaddingY = 50; 62 | 63 | static const int kPulldownWidth = 64; 64 | static const int kTextboxHeight = 14; 65 | static const int kTextboxWidth = 48; 66 | 67 | static const int kBankSelectorKey = 65536; 68 | static const int kPatchSelectorKey = 65537; 69 | 70 | static const int kGUIParamsStartAt = 1000; 71 | static const int kLFOParams = 8; // 8 parameters per LFO 72 | 73 | enum 74 | { 75 | kGUIParam_LFOButton1 = kGUIParamsStartAt, 76 | kGUIParam_LFOButton2, 77 | kGUIParam_LFOButton3, 78 | kGUIParam_VelButton, 79 | kGUIParam_ModButton, 80 | kGUIParam_ATButton, 81 | kGUIParam_DelButton, 82 | kGUIParam_ChrButton, 83 | kGUIParam_BitButton, 84 | kGUIParam_SaveEnter, 85 | kGUIParam_SaveOK, 86 | kGUIParam_SaveCancel 87 | }; 88 | 89 | enum velATMod_t 90 | { 91 | kVel = 0, 92 | kAT, 93 | kMod 94 | }; 95 | 96 | int m_curLFO; 97 | 98 | CControl* m_controls[VstCore::kNumParams]; 99 | CControl* m_LFOButtons[3]; 100 | CControl* m_velButton; 101 | CControl* m_atButton; 102 | CControl* m_modButton; 103 | CControl* m_velLabels[2]; 104 | CControl* m_atLabels[2]; 105 | CControl* m_modLabels[2]; 106 | 107 | CTextLabel* m_statusText; 108 | COptionMenu* m_patchMenu; 109 | COptionMenu* m_bankMenu; 110 | CTextEdit *m_saveFilenameField; 111 | CFrame *m_frame; 112 | CViewContainer *m_savePopup; 113 | 114 | CViewContainer *m_delayView; 115 | CViewContainer *m_chorusView; 116 | CViewContainer *m_bitcrushView; 117 | CControl *m_delayButton; 118 | CControl *m_chorusButton; 119 | CControl *m_bitcrushButton; 120 | 121 | CViewContainer *m_vuL; 122 | CViewContainer *m_vuR; 123 | 124 | std::vector m_lines; 125 | 126 | // When the status text is set, this is set to the number of idle() calls 127 | // until the status text goes blank again 128 | int m_statusTimeout; 129 | 130 | #ifdef DIGITS_PRO 131 | // Which LFO is currently shown? 132 | int m_activeLFO; 133 | #endif 134 | 135 | // Draw a panel with skew, a pulldown menu for waveshape, and a label 136 | void DrawOscPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 137 | int x, int y, oscType_t type); 138 | 139 | void DrawEnvPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 140 | int x, int y, bool isAmpEnv); 141 | 142 | void DrawMixPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 143 | int x, int y); 144 | 145 | void DrawPhasePanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 146 | int x, int y); 147 | 148 | // Show one LFO panel, hide the rest. whichLFO is the LFO #, starting from 0. 149 | void ShowLFOPanel(int whichLFO); 150 | 151 | // whichLFO is the number, starting from 0, of the LFO you want drawn 152 | void DrawLFOPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 153 | int x, int y, int whichLFO); 154 | 155 | // Show one FX panel, hide the rest. 156 | void ShowFXPanel(int which); 157 | 158 | void DrawFXPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 159 | int x, int y); 160 | 161 | void ShowVelATModPanel(velATMod_t mode); 162 | 163 | void DrawVelocityAftertouchPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 164 | int x, int y, velATMod_t forMode); 165 | 166 | void DrawMiscPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 167 | int x, int y); 168 | 169 | void DrawFilterPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 170 | int x, int y); 171 | 172 | void DrawMonoPolyPanel(CFrame* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 173 | int x, int y); 174 | 175 | void DrawPatchPanel(CFrame *destFrame, int x, int y); 176 | // Update the guts of the patch panel, which also updates the banks and patches 177 | // cache. Set bankChanged to true if changing banks. 178 | void UpdatePatchPanel(bool bankChanged=false); 179 | 180 | // Add a dial, spit back the handle for the label (handle for dial is in m_controls) 181 | CTextLabel *AddDial(CViewContainer* destFrame, CBitmap* dialImg, CBitmap* dialHandleImg, 182 | int x, int y, int paramNum, const char* label, float defaultValue=0); 183 | 184 | // Draw our snazzy backgroud 185 | void DrawLines(CFrame *destFrame); 186 | 187 | void SavePreset(std::string &fn); 188 | }; 189 | 190 | #endif 191 | 192 | -------------------------------------------------------------------------------- /src/digits/Patches.h: -------------------------------------------------------------------------------- 1 | #ifndef _PATCHES_H_ 2 | #define _PATCHES_H_ 3 | 4 | #define NUMPATCHES 44 5 | 6 | extern char presetBank[32][512]; 7 | 8 | //extern int s_patchLen[NUMPATCHES]; 9 | 10 | char *s_patchNames[] = { "INIT:Init Tone", 11 | "PAD: Bell Brass Pad", 12 | "PAD: Dream Pad", 13 | "PAD: Flanger Strings", 14 | "PAD: Ghost Choir", 15 | "PAD: String Ens.", 16 | "PAD: String Ens. Bright", 17 | "PAD: Wintery Pad", 18 | 19 | "SWP: HiSweep", 20 | "SWP: HiSweep-Overdrive", 21 | "SWP: Howling Tube", 22 | "SWP: Mean Sweeps", 23 | "SWP: Serious", 24 | 25 | "ARP: Eastern Arp", 26 | "ARP: Future Tines", 27 | "ARP: House Stabs", 28 | "ARP: POW!", 29 | "ARP: Quack! Quack!", 30 | "ARP: Thunky Arp", 31 | 32 | "LEAD:Bell Lead", 33 | "LEAD:Brass Lead", 34 | "LEAD:Brassy Slicer", 35 | "LEAD:Darius", 36 | "LEAD:Ghosts", 37 | "LEAD:Harsh Lead", 38 | "LEAD:Hollow Tube", 39 | "LEAD:HyperFlute", 40 | "LEAD:Raving Lunatic", 41 | "LEAD:ResoLead", 42 | "LEAD:SIDLead", 43 | "LEAD:SynReed", 44 | "LEAD:The Creeps", 45 | "LEAD:Solo Violin", 46 | 47 | "CHRD:Brass Ens.", 48 | "CHRD:Elec. Organ", 49 | "CHRD:Hi-Tone", 50 | "CHRD:Toy Piano", 51 | 52 | "BASS:404", 53 | "BASS:Chorused Bass", 54 | "BASS:FM Bass", 55 | "BASS:Flanger Bass", 56 | "BASS:PWM Bass", 57 | "BASS:Rubber Band", 58 | "BASS:Thunky Bass" 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/digits/PhaseDist.cpp: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #include 4 | #include "PhaseDist.h" 5 | #include "Voice.h" // PWM min/max defines 6 | #include "Tables.h" 7 | 8 | PhaseDist::PhaseDist() : 9 | m_ampBuf(0), 10 | m_shpBuf(0), 11 | m_fmInputAmt(0), 12 | m_fmInputAmt1(0), 13 | m_shaperMod(0), 14 | m_skew(0), 15 | m_delta(0), 16 | m_deltaDest(0), 17 | m_glide(0), 18 | m_glide1(0), 19 | m_pos(0), 20 | m_basisWave(0), 21 | m_pwmWidth(.5), 22 | m_keyScale(1.0f), 23 | m_lockShaperAmt(0) 24 | { 25 | m_lfoShaper[0] = m_lfoShaper[1] = m_lfoShaper[2] = 0; 26 | m_lfoPitch[0] = m_lfoPitch[1] = m_lfoPitch[2] = 0; 27 | m_lfoPWM[0] = m_lfoPWM[1] = m_lfoPWM[2] = 0; 28 | m_lfoBufs[0] = m_lfoBufs[1] = m_lfoBufs[2] = 0; 29 | } 30 | 31 | void PhaseDist::Render(float *fmIn, float *out, int len, float volume) 32 | { 33 | float *brightContour = m_shpBuf; 34 | float *ampContour = m_ampBuf; 35 | 36 | if (!ampContour || !out) 37 | return; 38 | 39 | float lastContour; 40 | if (brightContour) 41 | { 42 | // TODO: Make compatible with non-pro (see top of PhaseDist::Render) 43 | #ifdef DIGITS_PRO 44 | float lfoInfluence = ((m_lfoBufs[0][0]+1.0f)*.5f) * m_lfoShaper[0] 45 | + ((m_lfoBufs[1][0]+1.0f)*.5f) * m_lfoShaper[1] 46 | + ((m_lfoBufs[2][0]+1.0f)*.5f) * m_lfoShaper[2]; 47 | #else 48 | float lfoInfluence = ((m_lfoBufs[0][0]+1.0f)*.5f) * m_lfoShaper[0]; 49 | #endif 50 | float bright; 51 | if (m_lockShaperAmt) 52 | bright = m_lockShaperAmt; 53 | else 54 | bright = brightContour[0] - (brightContour[0] * lfoInfluence); 55 | lastContour = m_skew - (bright * m_skew * m_keyScale); 56 | } 57 | else 58 | lastContour = m_skew - (.90f * m_skew); 59 | 60 | float m1 = m_skew / lastContour; 61 | float m2 = (1.0f - m_skew) / (1.0f - lastContour); 62 | float b2 = 1.0f - m2; 63 | bool squareMode = m_shaperMod == .5f; 64 | if (squareMode) 65 | b2 *= .5f; 66 | 67 | // Calculate PWM shaper 68 | float lfoInfluence = m_lfoPWM[0] * m_lfoBufs[0][0] 69 | + m_lfoPWM[1] * m_lfoBufs[1][0] 70 | + m_lfoPWM[2] * m_lfoBufs[2][0]; 71 | float pwmWidth = m_pwmWidth + lfoInfluence; 72 | if (pwmWidth > Voice::kPWMMinimum + Voice::kPWMRange) pwmWidth = Voice::kPWMMinimum + Voice::kPWMRange; 73 | if (pwmWidth < Voice::kPWMMinimum) pwmWidth = Voice::kPWMMinimum; 74 | float m3 = .5f / pwmWidth; 75 | float m4 = (.5f) / (1.0f - pwmWidth); 76 | float b4 = 1.0f - m4; 77 | float pwmPos; 78 | if (m_pos < pwmWidth) 79 | pwmPos = m3*m_pos; 80 | else 81 | pwmPos = m4*m_pos + b4; 82 | 83 | float fmInputAmtDelta = (m_fmInputAmt1 - m_fmInputAmt) / (float)len; 84 | 85 | // Reset detail counter so this isn't happening twice in a row. This is a poor man's 86 | // optimization: This stuff should ONLY happen when m_detailCounter hits 0! Needs some 87 | // more thought. 88 | m_detailCounter = kDetailLevel; 89 | 90 | for (int i=0; i 1.0f) 122 | index *= m_shaperMod; 123 | 124 | if (m_fmInputAmt) 125 | if (m_basisWave == 0) 126 | out[i] += Tables::Cos(index + (m_fmInputAmt * fmIn[i])) * volume * ampContour[i]; 127 | else 128 | out[i] += Tables::Sin(index + (m_fmInputAmt * fmIn[i])) * volume * ampContour[i]; 129 | else 130 | if (m_basisWave == 0) 131 | out[i] += Tables::Cos(index) * volume; // Apply amp contour as last step since it's unified 132 | else 133 | out[i] += Tables::Sin(index) * volume; 134 | 135 | if (m_fmInputAmt != m_fmInputAmt1) 136 | m_fmInputAmt += fmInputAmtDelta; 137 | 138 | // Wrap oscillator 139 | float lfoInfluence = 0; 140 | if (m_lfoPitch[0]) 141 | lfoInfluence += m_lfoBufs[0][i] * m_lfoPitch[0]; 142 | if (m_lfoPitch[1]) 143 | lfoInfluence += m_lfoBufs[1][i] * m_lfoPitch[1]; 144 | if (m_lfoPitch[2]) 145 | lfoInfluence += m_lfoBufs[2][i] * m_lfoPitch[2]; 146 | m_pos += m_delta + (m_delta * lfoInfluence); 147 | while (m_pos >= 1.0f) 148 | { 149 | m_pos -= 1.0f; 150 | } 151 | 152 | // Recalculate linear equation 153 | if (--m_detailCounter <= 0) 154 | { 155 | if (brightContour) 156 | { 157 | #ifdef DIGITS_PRO 158 | float lfoInfluence = ((m_lfoBufs[0][i]+1.0f)*.5f) * m_lfoShaper[0] 159 | + ((m_lfoBufs[1][i]+1.0f)*.5f) * m_lfoShaper[1] 160 | + ((m_lfoBufs[2][i]+1.0f)*.5f) * m_lfoShaper[2]; 161 | if (lfoInfluence > 1.0f) lfoInfluence = 1.0f; 162 | #else 163 | float lfoInfluence = ((m_lfoBufs[0][i]+1.0f)*.5f) * m_lfoShaper[0]; 164 | #endif 165 | float bright; 166 | if (m_lockShaperAmt) 167 | bright = m_lockShaperAmt; 168 | else 169 | bright = brightContour[i] * (1.0f - lfoInfluence); 170 | 171 | //float bright = brightContour[i] - (brightContour[i] * ((m_lfoBuf[i]+1.0f)*.5f) * m_lfoShaper); 172 | lastContour = m_skew - (bright * m_skew * m_keyScale); 173 | } 174 | else 175 | lastContour = m_skew - (.9f * m_skew); 176 | m1 = m_skew / lastContour; 177 | m2 = (1.0f - m_skew) / (1.0f - lastContour); 178 | b2 = 1.0f - m2; 179 | if (squareMode) 180 | b2 *= .5f; 181 | 182 | // Move PWM 183 | #ifdef DIGITS_PRO 184 | float lfoInfluence = m_lfoPWM[0] * m_lfoBufs[0][0] 185 | + m_lfoPWM[1] * m_lfoBufs[1][0] 186 | + m_lfoPWM[2] * m_lfoBufs[2][0]; 187 | #else 188 | float lfoInfluence = m_lfoPWM[0] * m_lfoBufs[0][0]; 189 | #endif 190 | float pwmWidth = m_pwmWidth + lfoInfluence; 191 | if (pwmWidth > Voice::kPWMMinimum + Voice::kPWMRange) pwmWidth = Voice::kPWMMinimum + Voice::kPWMRange; 192 | if (pwmWidth < Voice::kPWMMinimum) pwmWidth = Voice::kPWMMinimum; 193 | 194 | m_detailCounter = kDetailLevel; 195 | } 196 | 197 | // Shape position using pwm shaper 198 | if (m_pos < pwmWidth) 199 | pwmPos = m3*m_pos; 200 | else 201 | pwmPos = m4*m_pos + b4; 202 | 203 | // Animate glide 204 | // m_delta = (m_glide*m_delta) + (m_glide1*m_deltaDest); 205 | } 206 | 207 | m_fmInputAmt = m_fmInputAmt1; 208 | } 209 | 210 | 211 | -------------------------------------------------------------------------------- /src/digits/PhaseDist.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #ifndef _PHASEDIST_ 4 | #define _PHASEDIST_ 5 | 6 | #include 7 | #include "SndBuf.h" 8 | #include "BufferManager.h" 9 | 10 | class PhaseDist 11 | { 12 | public: 13 | PhaseDist(); 14 | ~PhaseDist() {}; 15 | 16 | // Set the pitch in hz/sR (delta) 17 | void SetPitch(float delta) 18 | { 19 | m_delta = delta; 20 | m_deltaDest = delta; 21 | } 22 | 23 | void SetGlideDest(float delta) { m_deltaDest = delta; } 24 | 25 | // Render ADDING one buffer of audio (control rate chunk) 26 | void Render(float *fmIn, float *out, int len, float volume); 27 | 28 | // Brightness of the tone (filter cutoff) 29 | // void SetBright(float bright) { m_bright = m_skew - (bright * m_skew); } 30 | 31 | // Set FM input source (affects shaper position) 32 | // 0 if unused 33 | // void SetFMInput(SndBuf* fmInput) { m_fmInput = fmInput; } 34 | 35 | // Set FM input amount (affects shaper position) 36 | void SetFMInputAmt(float amt) { m_fmInputAmt1 = amt; } 37 | 38 | // How many times per cycle the shaper runs (2x for square) 39 | void SetShaperMod(float mod) { m_shaperMod = mod; } 40 | 41 | // Set skew point (.5 is normal for most CZ waves) 42 | void SetSkew(float skew) { m_skew = skew; } 43 | 44 | // Set basis waveform 45 | void SetBasis(int basis) { m_basisWave = basis; } 46 | 47 | void ResetPhase() { m_pos = 0; m_detailCounter = 0; } 48 | 49 | void SetGlideSpeed(float ms, float sR) 50 | { 51 | float sams = (ms/1000.0)*sR; 52 | m_glide = pow((float)M_E, (float)-1.0f/sams); 53 | m_glide1 = 1.0f - m_glide; 54 | } 55 | 56 | void SetPulseWidth(float width) { m_pwmWidth = width; } 57 | void SetBuffers(SndBuf* ampBuf, SndBuf* shpBuf, SndBuf** lfoBufs) 58 | { 59 | m_ampBuf = ampBuf->Data(); 60 | m_shpBuf = shpBuf->Data(); 61 | m_lfoBufs[0] = lfoBufs[0]->Data(); 62 | m_lfoBufs[1] = lfoBufs[1]->Data(); 63 | m_lfoBufs[2] = lfoBufs[2]->Data(); 64 | } 65 | 66 | void SetLFOShaper(int lfo, float value) { m_lfoShaper[lfo] = value; } 67 | void SetLFOPitch(int lfo, float value) { m_lfoPitch[lfo] = value; } 68 | void SetLFOPWM(int lfo, float value) { m_lfoPWM[lfo] = value; } 69 | 70 | // Get delta with modulation factored in (for keyscaling) 71 | float GetDelta() { return m_delta; } 72 | // Set keyscaling amount for shaper (shaper attenuation) 73 | void SetKeyScale(float x) { m_keyScale = x; } 74 | // See Voice for documentation on LockShaperTo 75 | void LockShaperTo(float val) { m_lockShaperAmt = val; } 76 | 77 | private: 78 | // Recalc slopes only every N samples 79 | static const int kDetailLevel = 16; 80 | 81 | float *m_ampBuf; 82 | float *m_shpBuf; 83 | float *m_lfoBufs[Tables::kNumLFOs]; 84 | 85 | float m_fmInputAmt; 86 | float m_fmInputAmt1; // zipper noise smoothing (new value) 87 | float m_shaperMod; 88 | float m_skew; 89 | 90 | float m_delta; 91 | // Delta destination (for slides) 92 | float m_deltaDest; 93 | // Coefficients for one-pole smoother (for slides) 94 | float m_glide; 95 | float m_glide1; 96 | float m_pos; 97 | int m_basisWave; 98 | float m_pwmWidth; 99 | 100 | // LFO severtity 101 | float m_lfoShaper[Tables::kNumLFOs]; 102 | float m_lfoPitch[Tables::kNumLFOs]; 103 | float m_lfoPWM[Tables::kNumLFOs]; 104 | 105 | // Shaper keyscaler 106 | float m_keyScale; 107 | // Lock shaper to this value (see Voice) 108 | float m_lockShaperAmt; 109 | 110 | int m_detailCounter; 111 | 112 | }; 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/digits/ResoGen.cpp: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #include 4 | #include "Tables.h" 5 | #include "ResoGen.h" 6 | 7 | ResoGen::ResoGen() : 8 | m_ampBuf(0), 9 | m_shpBuf(0), 10 | m_style(kSawQuarter), 11 | m_delta(0), 12 | m_pos1(0), 13 | m_pos2(0), 14 | m_flip(1.0f), 15 | m_pw(.5) 16 | { 17 | m_lfoBufs[0] = m_lfoBufs[1] = m_lfoBufs[2] = 0; 18 | m_lfoShaper[0] = m_lfoShaper[1] = m_lfoShaper[2] = 0; 19 | m_lfoPWM[0] = m_lfoPWM[1] = m_lfoPWM[2] = 0; 20 | m_lfoPitch[0] = m_lfoPitch[1] = m_lfoPitch[2] = 0; 21 | } 22 | 23 | void ResoGen::ResetPhase() 24 | { 25 | m_pos1 = 0; 26 | m_pos2 = 0; 27 | m_flip = 1.0f; 28 | } 29 | 30 | void ResoGen::Render(float *out, int len, float volume) 31 | { 32 | float* ampContour = m_ampBuf; 33 | float* brightContour = m_shpBuf; 34 | 35 | // Match the volume of the normal oscillator 36 | volume *= 2.0f; 37 | 38 | if (!ampContour || !brightContour || !out) 39 | return; 40 | 41 | // Calculate PWM shaper 42 | float m3 = .5f / m_pw; 43 | float m4 = (.5f) / (1.0f - m_pw); 44 | float b4 = 1.0f - m4; 45 | float pwmPos; 46 | if (m_pos2 < m_pw) 47 | pwmPos = m3*m_pos2; 48 | else 49 | pwmPos = m4*m_pos2 + b4; 50 | 51 | float sam; 52 | 53 | for (int i=0; i= 1.0f) 89 | m_pos1 -= 1.0f; 90 | while (m_pos2 >= 1.0f) 91 | { 92 | m_pos2 -= 1.0f; 93 | if (m_style == 2 || m_style == 3) 94 | m_flip *= -1.0f; 95 | } 96 | if (m_pos2 < m_pw) 97 | pwmPos = m3*m_pos2; 98 | else 99 | pwmPos = m4*m_pos2 + b4; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/digits/ResoGen.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #ifndef _RESOGEN_H_ 4 | #define _RESOGEN_H_ 5 | 6 | #include "SndBuf.h" 7 | 8 | class ResoGen 9 | { 10 | public: 11 | enum resoStyle_t 12 | { 13 | kSawQuarter, 14 | kSawHalf, 15 | kSquareQuarter, 16 | kSquareHalf 17 | }; 18 | 19 | ResoGen(); 20 | ~ResoGen() {} 21 | void SetPitch(float delta) { m_delta = delta; } 22 | 23 | void SetStyle(resoStyle_t style) { m_style = style; } 24 | 25 | // Render ADDING one buffer of audio (control rate chunk) 26 | void Render(float *out, int len, float volume=1.0f); 27 | 28 | // Brightness of the tone (filter cutoff) 29 | // void SetBright(float bright) { m_bright = 2.0f + (bright * 14.0f); } 30 | 31 | // Reset phase of oscillators 32 | void ResetPhase(); 33 | 34 | void SetPulseWidth(float width) { m_pw = width; } 35 | void SetBuffers(SndBuf *ampBuf, SndBuf *shpBuf, SndBuf **lfoBufs) 36 | { 37 | m_ampBuf = ampBuf->Data(); 38 | m_shpBuf = shpBuf->Data(); 39 | m_lfoBufs[0] = lfoBufs[0]->Data(); 40 | m_lfoBufs[1] = lfoBufs[1]->Data(); 41 | m_lfoBufs[2] = lfoBufs[2]->Data(); 42 | } 43 | void SetLFOShaper(int lfo, float value) { m_lfoShaper[lfo] = value; } 44 | void SetLFOPitch(int lfo, float value) { m_lfoPitch[lfo] = value; } 45 | void SetLFOPWM(int lfo, float value) { m_lfoPWM[lfo] = value; } 46 | 47 | private: 48 | float *m_ampBuf; 49 | float *m_shpBuf; 50 | float *m_lfoBufs[Tables::kNumLFOs]; 51 | float m_lfoShaper[Tables::kNumLFOs]; 52 | float m_lfoPitch[Tables::kNumLFOs]; 53 | float m_lfoPWM[Tables::kNumLFOs]; 54 | 55 | resoStyle_t m_style; 56 | float m_delta; 57 | // Position of slave (sine) 58 | float m_pos1; 59 | // Position of master (window) 60 | float m_pos2; 61 | // Multiplier for slave frequency 62 | // float m_bright; 63 | // Wave inversion for square patterns 64 | float m_flip; 65 | float m_pw; 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/digits/VstCore.h: -------------------------------------------------------------------------------- 1 | /* Phase Distortion Synthesizer (c) 2011 Louis Gorenfeld */ 2 | 3 | #ifndef _VSTCORE_H_ 4 | #define _VSTCORE_H_ 5 | 6 | #define VERSION_MAJ 0x1 7 | #define VERSION_MIN 0x5 8 | #define VERSION_PAT_MAJ 0x1 9 | #define VERSION_PAT_MIN 0x2 10 | 11 | #ifdef FAUX_VST_HEADER 12 | #include "FauxVST.h" 13 | #else 14 | #include "public.sdk/source/vst2.x/audioeffectx.h" 15 | #endif 16 | 17 | #include 18 | #include 19 | #include "PatchBankList.h" 20 | #include "Voice.h" 21 | #include "Chorus.h" 22 | #include "LFO.h" 23 | #include "Oversampler.h" 24 | 25 | #ifdef DIGITS_MULTICORE 26 | #include 27 | void* digits_helper(void* arg); 28 | #endif 29 | 30 | #ifdef DBGMCORE 31 | #define DEBUG_MCORE(...) { fprintf(stderr, __VA_ARGS__); } 32 | #define DEBUGFRAMESEPARATOR 33 | #else 34 | #define DEBUG_MCORE 35 | #endif 36 | 37 | class VstCore : public AudioEffectX 38 | { 39 | public: 40 | enum paramNums_t 41 | { 42 | kO1Skew = 0, 43 | kO1ShpMod, 44 | kO2Skew, 45 | kO2ShpMod, 46 | kO2Vol, 47 | #ifdef DIGITS_PRO 48 | kResetOscs, 49 | #endif 50 | kResoVol, 51 | kResoWave, 52 | kAmpAtt, 53 | kAmpDec, 54 | kAmpSus, 55 | kAmpFade, 56 | kAmpRel, 57 | kShpAtt, 58 | kShpDec, 59 | kShpSus, 60 | kShpFade, 61 | kShpRel, 62 | kShpMin, 63 | kShpMax, 64 | kFM, 65 | kDetune, 66 | kOctave, 67 | kBasisWave, 68 | kPulseWidth, 69 | kVelShaper, 70 | kVelVolume, 71 | kModShaper, 72 | kModLFO1Amp, 73 | #ifdef DIGITS_PRO 74 | kAftertouchShaper, 75 | kAftertouchLFO1Amp, 76 | #endif 77 | kLFORate, 78 | kLFOType, 79 | kLFODelay, 80 | kLFORepeat, 81 | kLFOShp, 82 | kLFOAmp, 83 | kLFOFrq, 84 | kLFOPWM, 85 | #ifdef DIGITS_PRO 86 | kLFO2Rate, 87 | kLFO2Type, 88 | kLFO2Delay, 89 | kLFO2Repeat, 90 | kLFO2Shp, 91 | kLFO2Amp, 92 | kLFO2Frq, 93 | kLFO2PWM, 94 | kLFO3Rate, 95 | kLFO3Type, 96 | kLFO3Delay, 97 | kLFO3Repeat, 98 | kLFO3Shp, 99 | kLFO3Amp, 100 | kLFO3Frq, 101 | kLFO3PWM, 102 | #endif 103 | kOrch, 104 | kDel_L, 105 | kDel_R, 106 | kDelWet, 107 | kDelFB, 108 | kDelLoss, 109 | kChrRate, 110 | kChrDepth, 111 | kChrDirtyClean, 112 | kChrTone, 113 | kChrWetDry, 114 | kChrFlang, 115 | kBitDiv, 116 | kBitBit, 117 | kBitBlend, 118 | #ifdef DIGITS_PRO 119 | kLockShaperForFilter, 120 | kFilterReso, 121 | kFilterMode, 122 | kMonoMode, 123 | kPortaSpeed, 124 | kAmpRateScale, 125 | kShpRateScale, 126 | kShpLevelScale, 127 | kPitchbendUp, 128 | kPitchbendDn, 129 | #endif 130 | kGain, 131 | kNumParams // Maximum value 132 | }; 133 | static const char* s_paramNames[]; 134 | 135 | 136 | #ifdef DIGITS_MULTICORE 137 | class HelperThread_t 138 | { 139 | public: 140 | // Constructor 141 | // rt_prio should be set to the priority we want the thread to be 142 | HelperThread_t(VstCore* core, Voice::voiceBuffers_t* bufs, int rt_prio); 143 | ~HelperThread_t(); 144 | 145 | // Signal the helper thread to start processing a chunk. Call from core. 146 | void StartProcessChunk(int len, int forBuf) 147 | { 148 | DEBUG_MCORE("c: StartProcessChunk: get lock\n"); 149 | pthread_mutex_lock(&m_beginChunkMutex); 150 | DEBUG_MCORE("c: StartProcessChunk: did processing = false, for buffer=%d\n", forBuf); 151 | m_curBuf = forBuf; 152 | m_chunkLen = len; 153 | m_didProcessing = false; 154 | pthread_mutex_unlock(&m_beginChunkMutex); 155 | DEBUG_MCORE("c: StartProcessChunk: release lock\n"); 156 | pthread_cond_signal(&m_beginChunkCond); 157 | DEBUG_MCORE("c: StartProcessChunk: signal helper for %u\n", forBuf); 158 | } 159 | bool DidProcessing() { return m_didProcessing; } 160 | // Call from core 161 | void Quit() 162 | { 163 | DEBUG_MCORE("Shutting down helper\n"); 164 | m_quitNow = true; 165 | StartProcessChunk(0, 0); 166 | pthread_join(m_thread, 0); 167 | DEBUG_MCORE("Done shutting down helper\n"); 168 | m_quitNow = false; 169 | } 170 | 171 | pthread_mutex_t* GetMutex() { return &m_beginChunkMutex; } 172 | 173 | // Do not call directly. This is called by the thread callback. 174 | void ThreadCore(); 175 | void SetOutputBuffer(float* buf) { m_outBuf = buf; } 176 | 177 | private: 178 | pthread_mutex_t m_beginChunkMutex; 179 | pthread_cond_t m_beginChunkCond; 180 | pthread_t m_thread; 181 | Voice::voiceBuffers_t* m_bufs; 182 | float* m_outBuf; 183 | int m_chunkLen; 184 | VstCore* m_vstCore; 185 | bool m_quitNow; 186 | // True if processing happened this frame 187 | bool m_didProcessing; 188 | unsigned int m_curBuf; 189 | }; 190 | #endif 191 | 192 | VstCore(audioMasterCallback audioMaster); 193 | ~VstCore(); 194 | 195 | // VST functions 196 | virtual VstInt32 getProgram () { return m_curProgram; } 197 | virtual void setProgram(VstInt32 program); 198 | virtual void getProgramName(char *name); 199 | virtual void setProgramName(char *name); 200 | // The non-VST SetProgramName. We use this because it's better, and Digits won't let 201 | // you permanently rename patches from solely within the DAW anyway/ 202 | // SetProgram is also a non-VST variant here (notice capitalization). Both these functions 203 | // are guaranteed to be safe to call without triggering any DAW-side behavior-- they're 204 | // solely superficial and are used to keep the UI in sync. 205 | void SetProgramName(std::string name) { m_curProgramName = name; } 206 | void SetProgram(int program) { m_curProgram = program; } 207 | virtual void processReplacing(float **ins, float **outs, VstInt32 frames); 208 | virtual VstInt32 processEvents(VstEvents *events); 209 | virtual VstInt32 canDo(char *text); 210 | virtual void setParameter(VstInt32 index, float value); 211 | virtual float getParameter(VstInt32 index); 212 | virtual void getParameterLabel(VstInt32 index, char *text); 213 | virtual void getParameterDisplay(VstInt32 index, char *text); 214 | virtual void getParameterName(VstInt32 index, char *text); 215 | virtual void setSampleRate(float sR); 216 | virtual void setBlockSize(VstInt32 blockSize); 217 | virtual bool getOutputProperties(VstInt32 index, VstPinProperties* prop); 218 | virtual bool getEffectName(char *name); 219 | virtual bool getVendorString(char *text); 220 | virtual bool getProductString(char *text); 221 | virtual VstInt32 getNumMidiInputChannels() { return 1; } 222 | virtual VstInt32 getNumMidiOutputChannels() { return 0; } 223 | void HandleMidiEvent(char* midiEvent); 224 | // Set chorus for either chorus or flanger operation 225 | void SetChorusFlanger(bool isChorus); 226 | 227 | // Save/Load functions 228 | virtual VstInt32 getChunk(void** data, bool isPreset); 229 | virtual VstInt32 setChunk(void* data, VstInt32 byteSize, bool isPreset = false); 230 | bool LoadFXP(const std::string& fn); 231 | bool SaveFXP(const std::string& fn); 232 | 233 | PatchBankList& GetPatchBankList() { return m_pbList; } 234 | 235 | void NoteOn(int pitch, int velocity); 236 | void NoteOff(int pitch); 237 | 238 | bool VoiceIsFree(int voiceNum) { return m_voices[voiceNum]->IsFree(); } 239 | bool VoiceIsSubVoice(int voiceNum) { return m_voices[voiceNum]->IsSubVoice(); } 240 | void VoiceRender(int voiceNum, float *out, int len, Voice::voiceBuffers_t *bufs, int debugvoice, int debugthread) 241 | { 242 | m_voices[voiceNum]->Render(out, len, bufs, true, debugthread); 243 | } 244 | 245 | unsigned int CurBuf() { return m_curBuf; } 246 | 247 | #ifdef DIGITS_MULTICORE 248 | // Allocate a helper thread and start it. This routine is not very smart, so use 249 | // it carefully. 250 | void StartHelper(int helperIndex); 251 | #endif 252 | 253 | void AllNotesOff(); 254 | void ResetPhases(); 255 | void ResetEngine(); 256 | 257 | private: 258 | static const int kNumVoices = 40; 259 | static const int kOctaves = 10; // Octaves that there are deltas for 260 | static const char* s_paramNamesChunk[]; 261 | 262 | int m_curProgram; 263 | std::string m_curProgramName; 264 | 265 | // This is for the editor window, but must persist between 266 | // editor window allocation/reallocations 267 | PatchBankList m_pbList; 268 | 269 | Voice *m_voices[kNumVoices]; 270 | Chorus m_chorus[2]; 271 | // Chorus or flanger mode? 272 | bool m_chorusMode; 273 | // Oversampler m_oversampler; 274 | // int m_oversampleAmt; 275 | 276 | typedef std::vector midiEvents_t; 277 | std::vector m_midiEvents; 278 | static float s_freqDelta[kOctaves*12]; 279 | // Orch (spread, supersaw, etc) mode variance amount 280 | float m_orch; 281 | // Overall gain of the sound 282 | float m_gain; 283 | // Voice is set to monophonic 284 | bool m_isMono; 285 | // Voice is set to always glide 286 | bool m_alwaysGlide; 287 | 288 | // Calculate deltas for each frequency (tied to sampling rate) 289 | void CalculateFreqDeltas(); 290 | // Get delta for MIDI note number 291 | float GetDelta(VstInt32 midiNoteNum); 292 | // Find lowest key pressed (used in mono mode) 293 | int FindLowestNote(); 294 | 295 | // 2 for now (dual core) 296 | Voice::voiceBuffers_t m_bufSets[2]; 297 | // The helper's extra buffers 298 | // 1 for now (dual core) 299 | SndBuf* m_helperOutBufs[1]; 300 | 301 | SndBuf* m_tempBuf; 302 | 303 | // Bitfield for which keys are on (mono mode) 304 | uint32_t m_keyBits[4]; 305 | 306 | // Frames left to write within the control rate-sized buffer 307 | // left to write out to the host's buffer, preserved 308 | // between processReplacing calls 309 | int m_writeLeft; 310 | BufferManager m_manager; 311 | 312 | // True if this key is held down (keybits) 313 | inline bool IsNoteOn(int pitch); 314 | 315 | // Very simple store of floating point settings 316 | // for our program data 317 | float m_simpleProgram[kNumParams]; 318 | 319 | // Voice allocation and stealing algorithm 320 | int NextFreeVoice(); 321 | 322 | // Count up on each key press so that we can 323 | // figure out which notes are oldest 324 | uint64_t m_timestampClock; 325 | // Where does the next control period start? This is carried 326 | // over from buffer to buffer. 327 | int m_nextSpan; 328 | 329 | // Dynamically allocated space in which to save one patch. 330 | // FXBs are not supported. This is only dynamic because the 331 | // patch length varies because it's string based, but only 332 | // varies between versions. It calculates the patch len on save. 333 | char *m_patchData; 334 | 335 | // Last status byte for "running status" MIDI feature 336 | int m_lastStatus; 337 | 338 | // DC filter coefficients 339 | float m_dc_a[2]; 340 | float m_dc_b[2]; 341 | float m_dc_out[2]; 342 | float m_dc_in[2]; 343 | 344 | // Delay lines for echo 345 | float *m_delL; 346 | float *m_delR; 347 | // Read/write pointers 348 | int m_del_wL; 349 | int m_del_wR; 350 | // Wrap for pointer index in samples 351 | int m_del_wrapL; 352 | int m_del_wrapR; 353 | float m_delWet; 354 | float m_delFB; 355 | // Last sample for high frequency decay (4-pole) 356 | float m_del_lastL[4]; 357 | float m_del_lastR[4]; 358 | float m_del_filterA; 359 | float m_del_filterB; 360 | // Delay lines for chorus 361 | 362 | 363 | // Lite mode for phat detune 364 | bool m_phatLite; 365 | 366 | // Last note-on pitch recorded (for always-glide mode) 367 | int m_lastPitch; 368 | 369 | // Pitch bend amounts in semitones 370 | int m_bendUpAmt; 371 | int m_bendDnAmt; 372 | 373 | // True if the oscillator phases are reset upon note on 374 | bool m_resetOscs; 375 | 376 | #ifdef DIGITS_MULTICORE 377 | HelperThread_t* m_helpers[1]; 378 | #endif 379 | 380 | int m_numCores; 381 | 382 | void PitchBend(float value); 383 | void ZeroPatch(); 384 | 385 | void ApplyDC(float *in, int len); 386 | 387 | // Current chunk buffer's number (keep incrementing; wrap-around is OK) 388 | // This is used to prevent the helper thread from waking up too late and 389 | // performing work too early on the following frame, which knocks it out of sync 390 | unsigned int m_curBuf; 391 | 392 | SndBuf *m_chorusDryBuf; 393 | }; 394 | 395 | #endif 396 | 397 | -------------------------------------------------------------------------------- /windows/Digits.rc: -------------------------------------------------------------------------------- 1 | #define APSTUDIO_READONLY_SYMBOLS 2 | 3 | ///////////////////////////////////////////////////////////////////////////// 4 | // 5 | // Bitmap 6 | // 7 | 8 | CosNoiseRockerV.png PNG DISCARDABLE "../Graphics/digits/CosNoiseRockerV.png" 9 | CosSinRockerV.png PNG DISCARDABLE "../Graphics/digits/CosSinRockerV.png" 10 | Dial_LCD.png PNG DISCARDABLE "../Graphics/digits/Dial_LCD.png" 11 | DialHandle_LCD.png PNG DISCARDABLE "../Graphics/digits/DialHandle_LCD.png" 12 | DigitsBG.png PNG DISCARDABLE "../Graphics/digits/DigitsBG.png" 13 | HSliderBG.png PNG DISCARDABLE "../Graphics/digits/HSliderBG.png" 14 | HSliderNub.png PNG DISCARDABLE "../Graphics/digits/HSliderNub.png" 15 | Logo.png PNG DISCARDABLE "../Graphics/digits/Logo.png" 16 | 17 | 18 | #ifndef _MAC 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // 21 | // Version 22 | // 23 | 1 VERSIONINFO 24 | FILEVERSION 1,0,0,0 25 | PRODUCTVERSION 2,1,0,0 26 | FILEFLAGSMASK 0x0L 27 | #ifdef _DEBUG 28 | FILEFLAGS 0x1L 29 | #else 30 | FILEFLAGS 0x0L 31 | #endif 32 | FILEOS 0x4L 33 | FILETYPE 0x2L 34 | FILESUBTYPE 0x0L 35 | BEGIN 36 | BLOCK "StringFileInfo" 37 | BEGIN 38 | BLOCK "000004e4" 39 | BEGIN 40 | VALUE "CompanyName", "Extent of the Jam\0" 41 | VALUE "FileDescription", "Digits VST\0" 42 | VALUE "FileVersion", "2.1.0" 43 | VALUE "InternalName", "Digits VST" 44 | VALUE "LegalCopyright", "Extent of the Jam\0" 45 | VALUE "OriginalFilename", "Digits" 46 | VALUE "ProductName", "Digits" 47 | VALUE "ProductVersion", "2.1.0.0" 48 | END 49 | END 50 | BLOCK "VarFileInfo" 51 | BEGIN 52 | VALUE "Translation", 0x0, 1252 53 | END 54 | END 55 | 56 | #endif // !_MAC 57 | -------------------------------------------------------------------------------- /windows/DigitsVST.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | Win32Proj 23 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82} 24 | 25 | 26 | 27 | DynamicLibrary 28 | true 29 | v140 30 | 31 | 32 | DynamicLibrary 33 | true 34 | v140 35 | 36 | 37 | DynamicLibrary 38 | false 39 | v140 40 | 41 | 42 | DynamicLibrary 43 | false 44 | v140 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | true 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | true 73 | 74 | 75 | 76 | WIN32;_DEBUG;_WINDOWS;_USRDLL;DIGITSVST_EXPORTS;DIGITS_PRO;%(PreprocessorDefinitions);_USE_MATH_DEFINES 77 | MultiThreadedDebugDLL 78 | Level3 79 | ProgramDatabase 80 | Disabled 81 | $(ProjectDir)\..\src\components;$(ProjectDir)\..\src\digits;$(ProjectDir)\..\sdks\vstsdk2.4;$(ProjectDir)\..\sdks\vstgui\plugin-bindings;..\sdks\vstsdk2.4\public.sdk\source\vst2.x;%(AdditionalIncludeDirectories) 82 | 83 | 84 | MachineX86 85 | true 86 | Windows 87 | vstplug.def 88 | 89 | 90 | 91 | 92 | WIN32;_DEBUG;_WINDOWS;_USRDLL;DIGITSVST_EXPORTS;DIGITS_PRO;%(PreprocessorDefinitions);_USE_MATH_DEFINES 93 | MultiThreadedDebugDLL 94 | Level3 95 | ProgramDatabase 96 | Disabled 97 | C:\Users\Louis\Desktop\DigitsVst\trunk\vstsdk2.4;C:\MinGW\msys\1.0\home\Louis\svnrepo\DigitsVst\vstsdk2.4;%(AdditionalIncludeDirectories) 98 | 99 | 100 | true 101 | Windows 102 | vstplug.def 103 | 104 | 105 | 106 | 107 | WIN32;_WINDOWS;_USRDLL;DIGITSVST_EXPORTS;DIGITS_PRO;%(PreprocessorDefinitions);_USE_MATH_DEFINES 108 | MultiThreadedDLL 109 | Level3 110 | ProgramDatabase 111 | $(ProjectDir)\..\src\components;$(ProjectDir)\..\src\digits;$(ProjectDir)\..\sdks\vstsdk2.4;$(ProjectDir)\..\sdks\vstgui\plugin-bindings;..\sdks\vstsdk2.4\public.sdk\source\vst2.x;%(AdditionalIncludeDirectories) 112 | MaxSpeed 113 | Default 114 | 115 | 116 | MachineX86 117 | true 118 | Windows 119 | true 120 | true 121 | vstplug.def 122 | false 123 | 124 | 125 | 126 | 127 | WIN32;_WINDOWS;_USRDLL;DIGITSVST_EXPORTS;DIGITS_PRO;%(PreprocessorDefinitions);_USE_MATH_DEFINES 128 | MultiThreadedDLL 129 | Level3 130 | ProgramDatabase 131 | C:\Users\Louis\Desktop\DigitsVst\trunk\vstsdk2.4;C:\MinGW\msys\1.0\home\Louis\svnrepo\DigitsVst\vstsdk2.4;%(AdditionalIncludeDirectories) 132 | MaxSpeed 133 | Default 134 | 135 | 136 | true 137 | Windows 138 | true 139 | true 140 | vstplug.def 141 | false 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /windows/Main.VC.opendb: -------------------------------------------------------------------------------- 1 | LouisLOUIS-PC -------------------------------------------------------------------------------- /windows/Main.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 14 for Windows Desktop 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DigitsVST", "DigitsVST.vcxproj", "{85DD9136-6EC3-A79C-BA32-4D011E0C9E82}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Debug|Win32.Build.0 = Debug|Win32 18 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Debug|x64.ActiveCfg = Debug|x64 19 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Debug|x64.Build.0 = Debug|x64 20 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Release|Win32.ActiveCfg = Release|Win32 21 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Release|Win32.Build.0 = Release|Win32 22 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Release|x64.ActiveCfg = Release|x64 23 | {85DD9136-6EC3-A79C-BA32-4D011E0C9E82}.Release|x64.Build.0 = Release|x64 24 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Debug|Win32.Build.0 = Debug|Win32 26 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Debug|x64.ActiveCfg = Debug|x64 27 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Debug|x64.Build.0 = Debug|x64 28 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Release|Win32.ActiveCfg = Release|Win32 29 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Release|Win32.Build.0 = Release|Win32 30 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Release|x64.ActiveCfg = Release|x64 31 | {930529B6-2B18-40F3-B6AB-31D87251B0E4}.Release|x64.Build.0 = Release|x64 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /windows/vstplug.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | VSTPluginMain 3 | main=VSTPluginMain --------------------------------------------------------------------------------