├── .gitignore ├── Delegate.h ├── Filter.cpp ├── Filter.h ├── IPlugMultiTargets_controls.h ├── MIDIReceiver.cpp ├── MIDIReceiver.h ├── OpenCL.cpp ├── OpenCL.h ├── Oscillator.cpp ├── Oscillator.h ├── Oscilloscope.cpp ├── Oscilloscope.h ├── README.md ├── Signal.h ├── Synthesis-aax.vcxproj ├── Synthesis-aax.vcxproj.filters ├── Synthesis-app.vcxproj ├── Synthesis-app.vcxproj.filters ├── Synthesis-rtas.def ├── Synthesis-rtas.vcxproj ├── Synthesis-rtas.vcxproj.filters ├── Synthesis-vst2.vcxproj ├── Synthesis-vst2.vcxproj.filters ├── Synthesis-vst2.vcxproj.user ├── Synthesis-vst3.vcxproj ├── Synthesis-vst3.vcxproj.filters ├── Synthesis-vst3.vcxproj.user ├── Synthesis.cbp ├── Synthesis.cpp ├── Synthesis.exp ├── Synthesis.h ├── Synthesis.props ├── Synthesis.rc ├── Synthesis.sln ├── Voice.cpp ├── Voice.h ├── VoiceManager.cpp ├── VoiceManager.h ├── app_wrapper ├── app_dialog.cpp ├── app_main.cpp ├── app_main.h ├── app_resource.h └── main.mm ├── installer ├── Synthesis-installer-bg.png ├── Synthesis.iss ├── Synthesis.pkgproj ├── changelog.txt ├── intro.rtf ├── license.rtf ├── readmeosx.rtf └── readmewin.rtf ├── makedist-mac.command ├── makedist-win.bat ├── manual └── Synthesis_manual.pdf ├── opencl_kernels.cl ├── reaper-project-au.RPP ├── reaper-project-au.RPP-bak ├── reaper-project-vst2.RPP ├── reaper-project-vst2.RPP-bak ├── resource.h ├── resources ├── English.lproj │ ├── InfoPlist.strings │ └── MainMenu.xib ├── Synthesis-AAX-Info.plist ├── Synthesis-AU-Info.plist ├── Synthesis-OSXAPP-Info.plist ├── Synthesis-Pages.xml ├── Synthesis-RTAS-Info.plist ├── Synthesis-VST2-Info.plist ├── Synthesis-VST3-Info.plist ├── Synthesis.entitlements ├── Synthesis.icns ├── Synthesis.ico └── img │ ├── bg.png │ ├── blackkey.png │ ├── knob.png │ ├── waveform.png │ └── whitekey.png ├── update_version.py └── validate_audiounit.command /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.sdf 3 | *.opensdf 4 | *.zip 5 | *.suo 6 | *.ncb 7 | *.vcproj.* 8 | *.pkg 9 | *.dmg 10 | *.depend 11 | *.layout 12 | *.mode1v3 13 | *.db 14 | *.LSOverride 15 | *.xcworkspace 16 | *.xcuserdata 17 | *.xcschememanagement.plist 18 | build-* 19 | ipch/* 20 | gui/* 21 | build/* 22 | build-mac/* 23 | *.xcconfig 24 | *.xcodeproj 25 | 26 | Icon? 27 | .DS_Stor* -------------------------------------------------------------------------------- /Filter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Filter.cpp 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 2/7/14. 6 | // 7 | // 8 | 9 | #include "Filter.h" 10 | 11 | // By Paul Kellett 12 | // http://www.musicdsp.org/showone.php?id=29 13 | 14 | double Filter::process(double inputValue) { 15 | buf0 += cutoff * (inputValue - buf0); 16 | buf1 += cutoff * (buf0 - buf1); 17 | switch (mode) { 18 | case FILTER_MODE_LOWPASS: 19 | return buf1; 20 | case FILTER_MODE_HIGHPASS: 21 | return inputValue - buf0; 22 | case FILTER_MODE_BANDPASS: 23 | return buf0 - buf1; 24 | default: 25 | return 0.0; 26 | } 27 | // buf0 += cutoff * (inputValue - buf0); 28 | // buf1 += cutoff * (buf0 - buf1); 29 | // buf2 += cutoff * (buf1 - buf0); 30 | // buf3 += cutoff * (buf2 - buf1); 31 | // switch (mode) { 32 | // case FILTER_MODE_LOWPASS: 33 | // return buf3; 34 | // case FILTER_MODE_HIGHPASS: 35 | // return inputValue - buf3; 36 | // case FILTER_MODE_BANDPASS: 37 | // return buf0 - buf3; 38 | // default: 39 | // return 0.0; 40 | // } 41 | } -------------------------------------------------------------------------------- /Filter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Filter.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 2/7/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__Filter__ 10 | #define __Synthesis__Filter__ 11 | 12 | class Filter { 13 | public: 14 | enum FilterMode { 15 | FILTER_MODE_LOWPASS = 0, 16 | FILTER_MODE_HIGHPASS, 17 | FILTER_MODE_BANDPASS, 18 | kNumFilterModes 19 | }; 20 | Filter() : 21 | cutoff(0.5), 22 | resonance(0.0), 23 | mode(FILTER_MODE_BANDPASS), 24 | buf0(0.0), 25 | buf1(0.0), 26 | buf2(0.0), 27 | buf3(0.0) 28 | { 29 | calculateFeedbackAmount(); 30 | }; 31 | double process(double inputValue); 32 | inline void setCutoff(double newCutoff) { cutoff = newCutoff; calculateFeedbackAmount(); }; 33 | inline void setResonance(double newResonance) { resonance = newResonance; calculateFeedbackAmount(); }; 34 | inline void setFilterMode(FilterMode newMode) { mode = newMode; } 35 | private: 36 | double cutoff; 37 | double resonance; 38 | FilterMode mode; 39 | double feedbackAmount; 40 | inline void calculateFeedbackAmount() { feedbackAmount = resonance + resonance/(1.0 - cutoff); } 41 | double buf0; 42 | double buf1; 43 | double buf2; 44 | double buf3; 45 | }; 46 | 47 | #endif /* defined(__Synthesis__Filter__) */ 48 | -------------------------------------------------------------------------------- /IPlugMultiTargets_controls.h: -------------------------------------------------------------------------------- 1 | class ITestPopupMenu : public IControl 2 | { 3 | private: 4 | IPopupMenu mMainMenu, mSubMenu; 5 | 6 | public: 7 | ITestPopupMenu(IPlugBase *pPlug, IRECT pR) 8 | : IControl(pPlug, pR, -1) 9 | { 10 | mMainMenu.AddItem("first item"); 11 | mMainMenu.AddItem("second item"); 12 | mMainMenu.AddItem("third item"); 13 | 14 | mSubMenu.AddItem("first item"); 15 | mSubMenu.AddItem("second item"); 16 | mSubMenu.AddItem("third item"); 17 | 18 | mMainMenu.AddItem("sub menu", &mSubMenu); 19 | } 20 | 21 | bool Draw(IGraphics* pGraphics) 22 | { 23 | return pGraphics->FillIRect(&COLOR_WHITE, &mRECT);; 24 | } 25 | 26 | void OnMouseDown(int x, int y, IMouseMod* pMod) 27 | { 28 | doPopupMenu(); 29 | 30 | Redraw(); // seems to need this 31 | SetDirty(); 32 | } 33 | 34 | void doPopupMenu() 35 | { 36 | IPopupMenu* selectedMenu = mPlug->GetGUI()->CreateIPopupMenu(&mMainMenu, &mRECT); 37 | 38 | if (selectedMenu == &mMainMenu) 39 | { 40 | int itemChosen = selectedMenu->GetChosenItemIdx(); 41 | selectedMenu->CheckItemAlone(itemChosen); 42 | DBGMSG("item chosen, main menu %i\n", itemChosen); 43 | } 44 | else if (selectedMenu == &mSubMenu) 45 | { 46 | int itemChosen = selectedMenu->GetChosenItemIdx(); 47 | selectedMenu->CheckItemAlone(itemChosen); 48 | DBGMSG("item chosen, sub menu %i\n", itemChosen); 49 | } 50 | else 51 | { 52 | DBGMSG("nothing chosen\n"); 53 | } 54 | } 55 | }; 56 | 57 | class ITestPopupMenuB : public IControl 58 | { 59 | private: 60 | IPopupMenu mMainMenu; 61 | 62 | public: 63 | ITestPopupMenuB(IPlugBase *pPlug, IRECT pR) 64 | : IControl(pPlug, pR, -1) 65 | { 66 | mMainMenu.SetMultiCheck(true); 67 | mMainMenu.AddItem("first item"); 68 | mMainMenu.AddItem("second item"); 69 | mMainMenu.AddItem("third item"); 70 | } 71 | 72 | bool Draw(IGraphics* pGraphics) 73 | { 74 | return pGraphics->FillIRect(&COLOR_WHITE, &mRECT);; 75 | } 76 | 77 | void OnMouseDown(int x, int y, IMouseMod* pMod) 78 | { 79 | doPopupMenu(); 80 | 81 | Redraw(); // seems to need this 82 | SetDirty(); 83 | } 84 | 85 | void doPopupMenu() 86 | { 87 | IPopupMenu* selectedMenu = mPlug->GetGUI()->CreateIPopupMenu(&mMainMenu, &mRECT); 88 | 89 | if(selectedMenu) 90 | { 91 | int idx = selectedMenu->GetChosenItemIdx(); 92 | selectedMenu->CheckItem(idx, !selectedMenu->IsItemChecked(idx)); 93 | 94 | WDL_String checkedItems; 95 | 96 | checkedItems.Append("checked: ", 1024); 97 | 98 | for (int i = 0; i < selectedMenu->GetNItems(); i++) 99 | { 100 | checkedItems.AppendFormatted(1024, "%i ", selectedMenu->IsItemChecked(i)); 101 | } 102 | 103 | DBGMSG("%s\n", checkedItems.Get()); 104 | } 105 | } 106 | }; 107 | 108 | class IPresetMenu : public IControl 109 | { 110 | private: 111 | WDL_String mDisp; 112 | public: 113 | IPresetMenu(IPlugBase *pPlug, IRECT pR) 114 | : IControl(pPlug, pR, -1) 115 | { 116 | mTextEntryLength = MAX_PRESET_NAME_LEN - 3; 117 | mText = IText(14, &COLOR_BLACK, "Arial", IText::kStyleNormal, IText::kAlignNear); 118 | } 119 | 120 | bool Draw(IGraphics* pGraphics) 121 | { 122 | int pNumber = mPlug->GetCurrentPresetIdx(); 123 | mDisp.SetFormatted(32, "%02d: %s", pNumber+1, mPlug->GetPresetName(pNumber)); 124 | 125 | pGraphics->FillIRect(&COLOR_WHITE, &mRECT); 126 | 127 | if (CSTR_NOT_EMPTY(mDisp.Get())) 128 | { 129 | return pGraphics->DrawIText(&mText, mDisp.Get(), &mRECT); 130 | } 131 | 132 | return true; 133 | } 134 | 135 | void OnMouseDown(int x, int y, IMouseMod* pMod) 136 | { 137 | if (pMod->R) 138 | { 139 | const char* pname = mPlug->GetPresetName(mPlug->GetCurrentPresetIdx()); 140 | mPlug->GetGUI()->CreateTextEntry(this, &mText, &mRECT, pname); 141 | } 142 | else 143 | { 144 | doPopupMenu(); 145 | } 146 | 147 | Redraw(); // seems to need this 148 | SetDirty(); 149 | } 150 | 151 | void doPopupMenu() 152 | { 153 | int numItems = mPlug->NPresets(); 154 | IPopupMenu menu; 155 | 156 | IGraphics* gui = mPlug->GetGUI(); 157 | 158 | int currentPresetIdx = mPlug->GetCurrentPresetIdx(); 159 | 160 | for(int i = 0; i< numItems; i++) 161 | { 162 | const char* str = mPlug->GetPresetName(i); 163 | if (i == currentPresetIdx) 164 | menu.AddItem(str, -1, IPopupMenuItem::kChecked); 165 | else 166 | menu.AddItem(str); 167 | } 168 | 169 | menu.SetPrefix(2); 170 | 171 | if(gui->CreateIPopupMenu(&menu, &mRECT)) 172 | { 173 | int itemChosen = menu.GetChosenItemIdx(); 174 | 175 | if (itemChosen > -1) 176 | { 177 | mPlug->RestorePreset(itemChosen); 178 | mPlug->InformHostOfProgramChange(); 179 | mPlug->DirtyParameters(); 180 | } 181 | } 182 | } 183 | 184 | void TextFromTextEntry(const char* txt) 185 | { 186 | WDL_String safeName; 187 | safeName.Set(txt, MAX_PRESET_NAME_LEN); 188 | 189 | mPlug->ModifyCurrentPreset(safeName.Get()); 190 | mPlug->InformHostOfProgramChange(); 191 | mPlug->DirtyParameters(); 192 | SetDirty(false); 193 | } 194 | }; 195 | 196 | class IPopUpMenuControl : public IControl 197 | { 198 | public: 199 | IPopUpMenuControl(IPlugBase *pPlug, IRECT pR, int paramIdx) 200 | : IControl(pPlug, pR, paramIdx) 201 | { 202 | mDisablePrompt = false; 203 | mDblAsSingleClick = true; 204 | mText = IText(14); 205 | } 206 | 207 | bool Draw(IGraphics* pGraphics) 208 | { 209 | pGraphics->FillIRect(&COLOR_WHITE, &mRECT); 210 | 211 | char disp[32]; 212 | mPlug->GetParam(mParamIdx)->GetDisplayForHost(disp); 213 | 214 | if (CSTR_NOT_EMPTY(disp)) 215 | { 216 | return pGraphics->DrawIText(&mText, disp, &mRECT); 217 | } 218 | 219 | return true; 220 | } 221 | 222 | void OnMouseDown(int x, int y, IMouseMod* pMod) 223 | { 224 | if (pMod->L) 225 | { 226 | PromptUserInput(&mRECT); 227 | } 228 | 229 | mPlug->GetGUI()->SetAllControlsDirty(); 230 | } 231 | 232 | //void OnMouseWheel(int x, int y, IMouseMod* pMod, int d){} //TODO: popup menus seem to hog the mousewheel 233 | 234 | }; 235 | 236 | // Key catcher is an icontrol but only its OnKeyDown() is called... after all the other controls have been tested to see if they want keyboard input 237 | class IKeyCatcher : public IControl 238 | { 239 | public: 240 | IKeyCatcher(IPlugBase* pPlug, IRECT pR) 241 | : IControl(pPlug, pR) {} 242 | 243 | // this never gets called but is needed for an IControl 244 | bool Draw(IGraphics* pGraphics) { return false; } 245 | 246 | bool OnKeyDown(int x, int y, int key) 247 | { 248 | switch (key) 249 | { 250 | //case KEY_SPACE: 251 | /// DBGMSG("Space\n"); 252 | // return true; 253 | case KEY_LEFTARROW:; 254 | DBGMSG("Left\n"); 255 | return true; 256 | case KEY_RIGHTARROW: 257 | DBGMSG("Right\n"); 258 | return true; 259 | case KEY_UPARROW:; 260 | DBGMSG("Up\n"); 261 | return true; 262 | case KEY_DOWNARROW: 263 | DBGMSG("Down\n"); 264 | return true; 265 | default: 266 | return false; 267 | } 268 | } 269 | }; 270 | 271 | class ITempoDisplay : public IControl 272 | { 273 | private: 274 | ITimeInfo* mTimeInfo; 275 | WDL_String mDisplay; 276 | 277 | public: 278 | ITempoDisplay(IPlugBase* pPlug, IRECT pR, IText* pText, ITimeInfo* pTimeInfo) 279 | : IControl(pPlug, pR) 280 | { 281 | mText = *pText; 282 | mTimeInfo = pTimeInfo; 283 | } 284 | 285 | bool Draw(IGraphics* pGraphics) 286 | { 287 | mDisplay.SetFormatted(80, "Tempo: %f, SamplePos: %i, PPQPos: %f", mTimeInfo->mTempo, (int) mTimeInfo->mSamplePos, mTimeInfo->mPPQPos); 288 | return pGraphics->DrawIText(&mText, mDisplay.Get(), &mRECT); 289 | } 290 | 291 | bool IsDirty() { return true;} 292 | }; 293 | 294 | class IKnobMultiControlText : public IKnobControl 295 | { 296 | private: 297 | IRECT mTextRECT, mImgRECT; 298 | IBitmap mBitmap; 299 | 300 | public: 301 | IKnobMultiControlText(IPlugBase* pPlug, IRECT pR, int paramIdx, IBitmap* pBitmap, IText* pText) 302 | : IKnobControl(pPlug, pR, paramIdx), mBitmap(*pBitmap) 303 | { 304 | mText = *pText; 305 | mTextRECT = IRECT(mRECT.L, mRECT.B-20, mRECT.R, mRECT.B); 306 | mImgRECT = IRECT(mRECT.L, mRECT.T, &mBitmap); 307 | mDisablePrompt = false; 308 | } 309 | 310 | ~IKnobMultiControlText() {} 311 | 312 | bool Draw(IGraphics* pGraphics) 313 | { 314 | int i = 1 + int(0.5 + mValue * (double) (mBitmap.N - 1)); 315 | i = BOUNDED(i, 1, mBitmap.N); 316 | pGraphics->DrawBitmap(&mBitmap, &mImgRECT, i, &mBlend); 317 | //pGraphics->FillIRect(&COLOR_WHITE, &mTextRECT); 318 | 319 | char disp[20]; 320 | mPlug->GetParam(mParamIdx)->GetDisplayForHost(disp); 321 | 322 | if (CSTR_NOT_EMPTY(disp)) 323 | { 324 | return pGraphics->DrawIText(&mText, disp, &mTextRECT); 325 | } 326 | return true; 327 | } 328 | 329 | void OnMouseDown(int x, int y, IMouseMod* pMod) 330 | { 331 | if (mTextRECT.Contains(x, y)) PromptUserInput(&mTextRECT); 332 | #ifdef RTAS_API 333 | else if (pMod->A) 334 | { 335 | if (mDefaultValue >= 0.0) 336 | { 337 | mValue = mDefaultValue; 338 | SetDirty(); 339 | } 340 | } 341 | #endif 342 | else 343 | { 344 | OnMouseDrag(x, y, 0, 0, pMod); 345 | } 346 | } 347 | 348 | void OnMouseDblClick(int x, int y, IMouseMod* pMod) 349 | { 350 | #ifdef RTAS_API 351 | PromptUserInput(&mTextRECT); 352 | #else 353 | if (mDefaultValue >= 0.0) 354 | { 355 | mValue = mDefaultValue; 356 | SetDirty(); 357 | } 358 | #endif 359 | } 360 | 361 | }; 362 | 363 | class IPeakMeterVert : public IControl 364 | { 365 | public: 366 | 367 | IPeakMeterVert(IPlugBase* pPlug, IRECT pR) 368 | : IControl(pPlug, pR) 369 | { 370 | mColor = COLOR_BLUE; 371 | } 372 | 373 | ~IPeakMeterVert() {} 374 | 375 | bool Draw(IGraphics* pGraphics) 376 | { 377 | //IRECT(mRECT.L, mRECT.T, mRECT.W , mRECT.T + (mValue * mRECT.H)); 378 | pGraphics->FillIRect(&COLOR_RED, &mRECT); 379 | 380 | //pGraphics->FillIRect(&COLOR_BLUE, &mRECT); 381 | 382 | IRECT filledBit = IRECT(mRECT.L, mRECT.T, mRECT.R , mRECT.B - (mValue * mRECT.H())); 383 | pGraphics->FillIRect(&mColor, &filledBit); 384 | return true; 385 | } 386 | 387 | bool IsDirty() { return true;} 388 | 389 | protected: 390 | IColor mColor; 391 | }; 392 | 393 | class IPeakMeterHoriz : public IPeakMeterVert 394 | { 395 | public: 396 | 397 | bool Draw(IGraphics* pGraphics) 398 | { 399 | pGraphics->FillIRect(&COLOR_BLUE, &mRECT); 400 | IRECT filledBit = IRECT(mRECT.L, mRECT.T, mRECT.L + (mValue * mRECT.W() ) , mRECT.B ); 401 | pGraphics->FillIRect(&mColor, &filledBit); 402 | return true; 403 | } 404 | }; -------------------------------------------------------------------------------- /MIDIReceiver.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MIDIReceiver.cpp 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/12/14. 6 | // 7 | // 8 | 9 | #include "MIDIReceiver.h" 10 | 11 | void MIDIReceiver::onMessageReceived(IMidiMsg* midiMessage) { 12 | IMidiMsg::EStatusMsg status = midiMessage->StatusMsg(); 13 | IMidiMsg::EControlChangeMsg controlChange = midiMessage->ControlChangeIdx(); 14 | // We're only interested in Note On/Off messages (not CC, pitch, etc.) 15 | if(status == IMidiMsg::kNoteOn || status == IMidiMsg::kNoteOff) { 16 | //mMidiQueue.Add(midiMessage); 17 | } 18 | if(status == IMidiMsg::kPitchWheel) { 19 | // printf("\nPITCH WHEEL! %f", midiMessage->PitchWheel()); 20 | } 21 | if(controlChange == IMidiMsg::kSustainOnOff) { 22 | // printf("\nSUSTAYN %f", midiMessage->ControlChange(controlChange)); 23 | } 24 | if(controlChange == IMidiMsg::kModWheel) { 25 | // printf("\nMOD WHEEEEL %f", midiMessage->ControlChange(controlChange)); 26 | } 27 | if(controlChange == IMidiMsg::kExpressionController) { 28 | // printf("\nEXPRESSISIIIOOON %f", midiMessage->ControlChange(controlChange)); 29 | } 30 | mMidiQueue.Add(midiMessage); 31 | } 32 | 33 | // this is called on every sample while we're generating a buffer; as long as there are messages in the queue, we're processing and removing them from the front (using Peek and Remove). But we only do this for MIDI messages whose mOffset isn't greater than the current offset into the buffer. This means that we process every message at the right sample, keeping the relative timing intact. 34 | // After reading noteNumber and velocity, the if statement distinguishes note on and off messages (no velocity is interpreted as note off). In both cases, we're keeping track of which notes are being played, as well as how many of them. We also update the mLast... members so the already mentioned last note priority happens. This is the place where we know the frequency has to change, so we're updating it here. Finally, the mOffset is incremented so that the receiver knows how far into the buffer it currently is. An alternative would be to pass the offset in as an argument. So we now have a class that can receive all incoming MIDI note on/off messages. It always keeps track of which notes are being played and what the last played note (and frequency) was. 35 | void MIDIReceiver::advance() { 36 | while (!mMidiQueue.Empty()) { 37 | IMidiMsg* midiMessage = mMidiQueue.Peek(); 38 | if (midiMessage->mOffset > mOffset) break; 39 | 40 | IMidiMsg::EStatusMsg status = midiMessage->StatusMsg(); 41 | int noteNumber = midiMessage->NoteNumber(); 42 | int velocity = midiMessage->Velocity(); 43 | 44 | // There are only note on/off messages in the queue, see ::OnMessageReceived 45 | if (status == IMidiMsg::kNoteOn && velocity) { 46 | if(mKeyStatus[noteNumber] == false) { 47 | mKeyStatus[noteNumber] = true; 48 | mNumKeys += 1; 49 | noteOn(noteNumber, velocity); 50 | } 51 | } else { 52 | if(mKeyStatus[noteNumber] == true) { 53 | mKeyStatus[noteNumber] = false; 54 | mNumKeys -= 1; 55 | noteOff(noteNumber, velocity); 56 | } 57 | } 58 | 59 | IMidiMsg::EControlChangeMsg controlChange = midiMessage->ControlChangeIdx(); 60 | switch (controlChange) { 61 | case IMidiMsg::kSustainOnOff: 62 | sustainChange(midiMessage->ControlChange(controlChange)); 63 | break; 64 | case IMidiMsg::kModWheel: 65 | modChange(midiMessage->ControlChange(controlChange)); 66 | break; 67 | case IMidiMsg::kExpressionController: 68 | expressionChange(midiMessage->ControlChange(controlChange)); 69 | break; 70 | default: 71 | break; 72 | } 73 | 74 | mMidiQueue.Remove(); 75 | } 76 | mOffset++; 77 | } -------------------------------------------------------------------------------- /MIDIReceiver.h: -------------------------------------------------------------------------------- 1 | // 2 | // MIDIReceiver.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/12/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__MIDIReceiver__ 10 | #define __Synthesis__MIDIReceiver__ 11 | 12 | #include 13 | #pragma clang diagnostic push 14 | #pragma clang diagnostic ignored "-Wextra-tokens" 15 | #include "IPlug_include_in_plug_hdr.h" 16 | #pragma clang diagnostic pop 17 | 18 | #include "IMidiQueue.h" 19 | #include "Signal.h" 20 | using Gallant::Signal1; 21 | using Gallant::Signal2; //Signal2 is a signal that passes two parameters. There's Signal0 through Signal8, so you can choose depending on how many parameters you need. 22 | 23 | class MIDIReceiver { 24 | 25 | public: 26 | MIDIReceiver() : 27 | mNumKeys(0), 28 | mOffset(0) { 29 | for (int i = 0; i < keyCount; i++) { 30 | mKeyStatus[i] = false; 31 | } 32 | }; 33 | 34 | // Returns true if the key with a given index is currently pressed 35 | inline bool getKeyStatus(int keyIndex) const { return mKeyStatus[keyIndex]; } 36 | // Returns the number of keys currently pressed 37 | inline int getNumKeys() const { return mNumKeys; } 38 | void advance(); 39 | void onMessageReceived(IMidiMsg* midiMessage); 40 | inline void Flush(int nFrames) { mMidiQueue.Flush(nFrames); mOffset = 0; } 41 | inline void Resize(int blockSize) { mMidiQueue.Resize(blockSize); } 42 | 43 | // both of these signal generators will pass two ints 44 | Signal2< int, int > noteOn; 45 | Signal2< int, int > noteOff; 46 | Signal1< double > sustainChange; 47 | Signal1< double > expressionChange; 48 | Signal1< double > modChange; 49 | 50 | private: 51 | IMidiQueue mMidiQueue; 52 | static const int keyCount = 128; 53 | int mNumKeys; // how mnay keys are being played at the moment (via midi) 54 | bool mKeyStatus[keyCount]; // array of on/off for each key (index is note number) 55 | int mOffset; 56 | }; 57 | 58 | #endif /* defined(__Synthesis__MIDIReceiver__) */ 59 | -------------------------------------------------------------------------------- /OpenCL.h: -------------------------------------------------------------------------------- 1 | // 2 | // OpenCL.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/22/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__OpenCL__ 10 | #define __Synthesis__OpenCL__ 11 | 12 | #define __NO_STD_VECTOR // Use cl::vector instead of STL vector 13 | #define __NO_STD_STRING // Use cl::string instead of STL string 14 | #define __CL_ENABLE_EXCEPTIONS 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | //#include 24 | #include 25 | using namespace cl; 26 | 27 | #define BLOCK_SIZE 256 28 | #define NUM_CHANNELS 2 29 | #define MAX_VOICES 16 30 | #define NUM_VOICE_PARAMS 5 // num params per voice - mTime, mFrequency, mVelocity, randStringMult, randomSeed 31 | //#define numAuxiliaryParams 4 32 | #define NUM_INSTRUMENT_PARAMS 7 // linear term, squared term, cubic term, brightness A, brightness B, pitch bend (coarse), pitch bend (fine) 33 | 34 | 35 | class OpenCL { 36 | public: 37 | friend class VoiceManager; 38 | OpenCL() : 39 | mTime(0.0f), 40 | sampleRate(44100.0f), 41 | NUM_PARTIALS(140), 42 | mStringDetuneRange(0.001f), 43 | mDamping(2.5f), 44 | mTimeStep(1.0f/44100) 45 | // instrumentData[0.3, 1.0f, 0.3f] 46 | { 47 | 48 | /// init variables 49 | 50 | //MIDIParams[0] = 0.0f; 51 | 52 | 53 | 54 | // try { 55 | // Platform::get(&platforms); 56 | // 57 | // // Select the default platform and create a context using this platform and the GPU 58 | // cl_context_properties cps[3] = { 59 | // CL_CONTEXT_PLATFORM, 60 | // (cl_context_properties)(platforms[0])(), 61 | // 0 62 | // }; 63 | // 64 | // context = cl::Context( CL_DEVICE_TYPE_GPU, cps); 65 | // 66 | // devices = context.getInfo(); 67 | // 68 | // //std::cout << "DEVICES = " << devices; 69 | // 70 | // // Print out details of the first device 71 | // std::cout << "\nSMOKE Device: " << devices[0].getInfo().c_str(); 72 | // std::cout << "\nVersion: " << devices[0].getInfo().c_str(); 73 | // std::cout << "\nMax Compute Units: " << devices[0].getInfo(); 74 | // std::cout << "\nGlobal Memory Size: " << devices[0].getInfo()/1000000.0 << " MB"; 75 | // std::cout << "\nLocal Memory Size: " << devices[0].getInfo() << " bytes"; 76 | // std::cout << "\nMax Memory Object Size: " << devices[0].getInfo() << " bytes"; 77 | // std::cout << "\nMax Work Group Size: " << devices[0].getInfo(); 78 | // std::cout << "\nMax Work Item Dimensions: " << devices[0].getInfo(); 79 | // //std::cout << "\nMax Work Item Sizes: " << devices[0].getInfo(); 80 | // std::cout << "\nPreferred Vector Width (Float): " << devices[0].getInfo(); 81 | // std::cout << "\nPreferred Vector Width (Double): " << devices[0].getInfo(); 82 | // //std::cout << "\nExtensions: " << devices[0].getInfo().c_str(); 83 | // 84 | // 85 | // // Create a command queue and use the first device 86 | // queue = CommandQueue(context, devices[0], CL_QUEUE_PROFILING_ENABLE); 87 | // 88 | // // Read source file 89 | // std::ifstream sourceFile("opencl_kernels.cl"); 90 | // std::string sourceCode(std::istreambuf_iterator(sourceFile), (std::istreambuf_iterator())); 91 | // Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length()+1)); 92 | // 93 | // // Make program of the source code in the context 94 | // program = Program(context, source); 95 | // 96 | // // Build program for these specific devices 97 | // program.build(devices, "-cl-finite-math-only -cl-no-signed-zeros"); 98 | // 99 | // string log = program.getBuildInfo(devices[0]); 100 | // 101 | // std::cout << "\n\n\n" << log.c_str(); 102 | // 103 | // // Make kernel 104 | // oscillatorKernel = Kernel(program, "oscillator"); 105 | // addVoicesKernel = Kernel(program, "add_voices"); 106 | // 107 | // } catch(cl::Error error) { 108 | // std::cout << error.what() << "(" << error.err() << ")" << std::endl; 109 | // cl::STRING_CLASS buildlog; 110 | // buildlog = program.getBuildInfo(devices[0]); 111 | // std::cout << "\n\n\n" << buildlog.c_str() << "\n\n\n"; 112 | // } 113 | 114 | 115 | }; 116 | void initOpenCL(); 117 | inline boost::array getBlockOfSamples() { 118 | calculateSamples(); 119 | mTime += mTimeStep * BLOCK_SIZE; 120 | return blockOfSamples; 121 | } 122 | float voicesEnergy[MAX_VOICES*BLOCK_SIZE]; 123 | 124 | private: 125 | //void runOpenCL(); 126 | //float *samples[128]; 127 | boost::array blockOfSamples; 128 | void calculateSamples(); 129 | 130 | vector platforms; 131 | Context context; 132 | vector devices; 133 | CommandQueue queue; 134 | Program program; 135 | Kernel oscillatorKernel; 136 | Kernel addVoicesKernel; 137 | 138 | short NUM_PARTIALS; // max number of partials to calculate for each note 139 | short NUM_ACTIVE_VOICES; 140 | 141 | //short NUM_CHANNELS; 142 | 143 | int GLOBAL_SIZE; 144 | int MAX_WORK_GROUP_SIZE; 145 | int WORK_GROUP_SIZE; 146 | 147 | float mTime, mTimeStep; 148 | float sampleRate; 149 | float voicesData[MAX_VOICES*NUM_VOICE_PARAMS]; 150 | //float voicesDamping[MAX_VOICES*BLOCK_SIZE]; 151 | float MIDIParams[3]; // sustain, expression, mod 152 | float mModPrevious, mModCurrent, mModSmoothed; 153 | std::queue modBuffer; 154 | // boost::circular_buffer modBuffer(); 155 | 156 | float mB; // inharmonicity coefficient 157 | float mStringDetuneRange; 158 | float mPartialDetuneRange; 159 | float mDamping; 160 | 161 | float instrumentData[NUM_INSTRUMENT_PARAMS]; // linear term, squared term, cubic term 162 | 163 | Buffer voicesDataBuffer, voicesEnergyBuffer, instrumentDataBuffer, voicesSampleBuffer, outputSampleBuffer, ADSRBuffer; 164 | NDRange globalSize, localSize, globalSizeAdder, localSizeAdder; 165 | }; 166 | 167 | #endif /* defined(__Synthesis__OpenCL__) */ 168 | -------------------------------------------------------------------------------- /Oscillator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Oscillator.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/12/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__Oscillator__ 10 | #define __Synthesis__Oscillator__ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "Signal.h" 16 | #include 17 | 18 | 19 | 20 | class Oscillator { 21 | 22 | public: 23 | enum OscillatorMode { 24 | OSCILLATOR_MODE_SINE, 25 | OSCILLATOR_MODE_SAW, 26 | OSCILLATOR_MODE_SQUARE, 27 | OSCILLATOR_MODE_TRIANGLE, 28 | kNumOscillatorModes 29 | }; 30 | void setMode(OscillatorMode mode); 31 | void setFrequency(double frequency); 32 | void setVelocity(int velocity); 33 | void setPitchMod(double amount); 34 | void setSampleRate(double sampleRate); 35 | void updateInstrumentModel(); 36 | void updateInharmonicityCoeff(double mBNew); 37 | void updateNumPartials(int mNumPartialsNew); 38 | inline double getTime() { return mTime; } 39 | //inline void setMuted(bool muted) { isMuted = muted; } 40 | inline void resetTime() { mTime = 0.0; } // resets time counter whenever a new noteOn signal is triggered 41 | inline void reset() { mTime = 0.0; updateInstrumentModel(); }; 42 | boost::array nextSample(); 43 | 44 | void generate(double* buffer, int nFrames); 45 | 46 | 47 | Oscillator() : // this is the constructor's "initializer list" 48 | mOscillatorMode(OSCILLATOR_MODE_SINE), 49 | mPI(2*acos(0.0)), 50 | twoPI(2 * mPI), 51 | mTimeStep(1.0 / 44100.0), 52 | 53 | mNumStringsPerNote(2), 54 | 55 | mStringDetuneRange(0.001), // .002 is good 56 | mStringRatio(1.0), // calculated dynamically based on mStringDetuneRange (value here doesn't matter) 57 | mB(0.0001), // sample inharmonic coefficient for A2 piano string, default .00012, .0012 sounds super cool! .0002 is subtler 58 | 59 | // for lorenz 60 | mLX(0.0), 61 | mLXdot(0.0), 62 | mLY(1.0), 63 | mLYdot(0.0), 64 | mLZ(1.05), 65 | mLZdot(0.0), 66 | mLSigma(10.0), 67 | mLRho(24.0), // default 28.0 68 | mLBeta(8.0/3.0), 69 | mLRand(1.0), 70 | 71 | // for tinkerbell map 72 | mTX(-0.72), 73 | mTY(-0.64), 74 | mTXnew(0.0), 75 | mTYnew(0.0), 76 | mTa(0.9), 77 | mTb(-0.6013), 78 | mTc(2.0), 79 | mTd(0.50), 80 | 81 | mCalculateNoisyTransient(true), 82 | mAttack(3000), // the higher, the shorter the attack. 3000 is good soft noisy attack 83 | mTransientLength(0.500), // length in seconds to continue calculating transients for 84 | mPartialsDelay(0.005), // length in seconds to delay partial synthesis after note trigger (so it starts slightly after hit/pluck/excitation/transient) 85 | 86 | // string hit location stuff 87 | mStringHitLocation(0.166), 88 | mLocationBasedAmplitude(1.0), 89 | 90 | mFrequency(440.0), 91 | mLastFrequency(220.0), // could be anything, just needs to be different than mFrequency for starters, or else comparison returns true on first note strike after program init (and we want it to return false) 92 | mVelocity(0), 93 | mPitchMod(0.0), 94 | mNumPartials(30), 95 | mMaxFreq(20000.0), // eventually might want to limit this to human hearing for performance reasons - will be generating partials way above human hearing at 96k, 192k, etc. sample rates 96 | mMaxPartials(500.0), // max number of partials possible (governs things like array length for storing slightly-inharmonic partial frequencies) 97 | //mPartialInharmonicityCoeffs({ }) 98 | mPartialFrequency(0.0), 99 | mAmplitude(0.0), 100 | mPartialInharmonicityCoeff(1.0) 101 | { 102 | updateTime(); 103 | updateInstrumentModel(); 104 | seedRNG(); 105 | }; 106 | 107 | private: 108 | 109 | OscillatorMode mOscillatorMode; 110 | const double mPI; 111 | const double twoPI; 112 | const double mMaxFreq; // cutoff frequency, above which do not generate any partials (for human hearing limits and performance) 113 | const double mMaxPartials; 114 | const double mNumStringsPerNote; 115 | double mB; // inharmonicity coefficient --> B = pi^2 * Q * S * K^2 / (T * l^2) --> see Evernote "Research" for details 116 | 117 | int mVelocity; 118 | double mPitchMod; 119 | 120 | double mFrequency; 121 | double mLastFrequency; // for storing the last frequency 122 | static double mSampleRate; 123 | double mStringRatio; // ratio of frequencies of one string to the other (per note) 124 | double mPartialInharmonicityCoeff; // calculated dynamically for each partial in nextSample() 125 | double mPartialFrequencyMultipliers [1000]; // twice as many as inharmonicitycoeffs b/c allowing for two strings (double the number of partials) 126 | double mPartialFrequencies [1000]; // just calculating partial freq directly! 127 | double mPartialAmplitudes [1000]; // same as above 128 | double mPartialPanValues [1000]; 129 | double mFrequencies [10]; // allows for up to X strings per note 130 | double mPartialFrequency; 131 | double mTime; 132 | double mTimeStep; // seconds per sample (for keeping running total of time) 133 | //unsigned long long mSampleIndex; // running total of which sample index we're on, reset at every note trigger. should be good for 13.26 million years of samples at 44.1kHz 134 | double mAmplitude; // used for calculating partial amplitudes 135 | 136 | // strange attractor variables 137 | double mLX; 138 | double mLXdot; 139 | double mLY; 140 | double mLYdot; 141 | double mLZ; 142 | double mLZdot; 143 | double mLSigma; 144 | double mLRho; 145 | double mLBeta; 146 | double mLRand; 147 | 148 | // for Tinkerbell map 149 | double mTX; 150 | double mTXnew; 151 | double mTY; 152 | double mTYnew; 153 | double mTa; 154 | double mTb; 155 | double mTc; 156 | double mTd; 157 | 158 | double mCalculateNoisyTransient; // whether or not to calculate noise 159 | double mAttack; 160 | double mTransientLength; 161 | double mPartialsDelay; // delay partial synthesis by a small amount of time, to simulate the attack/hammer/pluck/excitation happening slightly before the actual partials sounding 162 | 163 | double values[2]; // temporary array for summing partials together 164 | boost::array samples; // container for returning samples (or blocks of samples, when I start using OpenCL) 165 | 166 | double noise; // var for calculating chaos noise 167 | 168 | double mStringHitLocation; 169 | double mLocationBasedAmplitude; 170 | 171 | double mNumPartials; // probably don't need double precision on this! doing float instead of int b/c need to divide by float when calculating partial amplitude, couldn't figure out any other way to do it 172 | double mStringDetuneRange; // multiplier for slightly detuning individual strings for the same note 173 | 174 | 175 | void getLocationBasedAmplitude(int i); 176 | void updateTime(); 177 | inline void seedRNG() { srand(static_cast(time(0))); } // seed random generator, once per program run 178 | 179 | }; 180 | 181 | #endif /* defined(__Synthesis__Oscillator__) */ 182 | -------------------------------------------------------------------------------- /Oscilloscope.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Oscilloscope.cpp 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/16/14. 6 | // 7 | // 8 | 9 | #include "Oscilloscope.h" 10 | #include "IControl.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | 18 | void Oscilloscope::restoreContext() { 19 | CGLSetCurrentContext(NULL); 20 | } 21 | 22 | long Oscilloscope::createContext() { 23 | const GLubyte *glstring; 24 | 25 | GLint npix; 26 | CGLPixelFormatObj PixelFormat; 27 | 28 | const CGLPixelFormatAttribute attributes[] = { 29 | //kCGLPFAOffScreen, 30 | // kCGLPFAColorSize, (CGLPixelFormatAttribute)8, 31 | // kCGLPFADepthSize, (CGLPixelFormatAttribute)16, 32 | kCGLPFAAccelerated, (CGLPixelFormatAttribute)0 33 | }; 34 | 35 | // Create context if none exists 36 | CGLChoosePixelFormat(attributes, &PixelFormat, &npix); 37 | 38 | if (PixelFormat == NULL) { 39 | DBGMSG("Could not get pixel format."); 40 | return 1; 41 | } 42 | 43 | CGLCreateContext(PixelFormat, NULL, &mGLContext); 44 | 45 | if (mGLContext == NULL) { 46 | DBGMSG("Could not create rendering context."); 47 | return 1; 48 | } 49 | 50 | // Set the current context 51 | if(setContext()) 52 | return 1; 53 | 54 | // Check OpenGL functionality: 55 | glstring = glGetString(GL_EXTENSIONS); 56 | 57 | if(!gluCheckExtension((const GLubyte *)"GL_EXT_framebuffer_object", glstring)) { 58 | DBGMSG("The GL_EXT_framebuffer_object extension is not supported on this system."); 59 | return 1; 60 | } 61 | restoreContext(); 62 | return 0; 63 | } 64 | 65 | void Oscilloscope::destroyContext() { 66 | if (mGLContext != NULL) 67 | CGLDestroyContext(mGLContext); 68 | } 69 | 70 | long Oscilloscope::setContext() { 71 | // Set the current context 72 | if(CGLSetCurrentContext(mGLContext)) { 73 | DBGMSG("Could not make context current."); 74 | return 1; 75 | } 76 | return 0; 77 | } 78 | 79 | void Oscilloscope::initBuffer() { 80 | //boost::circular_buffer cb(100); 81 | for (int i = 0; i < bufferSize; i++) { 82 | //cb.push_back(0.0); 83 | buffer[0][i] = buffer[1][i] = 0; 84 | } 85 | } 86 | 87 | void Oscilloscope::updatePixelColors() { 88 | //pixBlack = LICE_RGBA(0, 0, 0, 255); 89 | //pixGreen = LICE_RGBA(rgbR, rgbG, rgbB, 255); 90 | //pixLightGreen = LICE_RGBA(200,255,200,255); 91 | //pixWhite = LICE_RGBA(255,255,255,255); 92 | // rgbR = rand() % 128 + 128; 93 | // rgbG = rand() % 128 + 128; 94 | // rgbB = rand() % 128 + 128; 95 | // pixGreen = LICE_RGBA(255, 60, 10, 255); 96 | pixGreen = LICE_RGBA(55, 255, 55, 255); 97 | } 98 | 99 | void Oscilloscope::updateLastSample(double sampleL, double sampleR) { 100 | //cb.push_back(sample); 101 | if (iterator > (bufferSize - 1)) { 102 | iterator = 0; 103 | } 104 | buffer[0][iterator] = sampleL; 105 | buffer[1][iterator] = sampleR; 106 | iterator++; 107 | } 108 | 109 | bool Oscilloscope::Draw(IGraphics* pGraphics) { 110 | 111 | // render buffer example: https://github.com/olilarkin/wdl-ol/blob/master/IPlugExamples/IPlugOpenGL/IPlugOpenGL.h 112 | 113 | //const int width = mRECT.W(); 114 | //const int width = mRECT.W();//600;//bufferSize * 3; 115 | //const int height = mRECT.H(); 116 | 117 | // Set context 118 | if (setContext()) 119 | return false; 120 | 121 | // Reset The Current Viewport 122 | restoreContext(); 123 | 124 | /// display pixels on screen 125 | 126 | //std::cout << pGraphics->FPS() << " fps\n"; 127 | 128 | // draw black pixels over the whole screen (or would just drawing a black rectangle be faster? probably... or just a "clear screen" option? 129 | // for (int y = 0; y < height; y++) { 130 | // for (int x = 0; x < width; x++) { 131 | // LICE_PutPixel(pGraphics->GetDrawBitmap(), mRECT.L + x, mRECT.B - y, pixBlack, 0.1, LICE_BLIT_MODE_COPY | LICE_BLIT_USE_ALPHA); 132 | // } 133 | // } 134 | 135 | int xPos = 500; 136 | int yPos = 300; 137 | int xMult = 4000; // 16000 works well, doesn't overflow 1000x1000; 20000 is bigger, but clips a little 138 | int yMult = 1000; // 4000 works well, doesn't overflow 1000x1000; 6000 is bigger, but clips a little 139 | 140 | 141 | /// phase scope / Lissajous 142 | 143 | for (int a = 0; a < bufferSize-1; a++) { 144 | int xPhaseOffset = mRECT.L + xPos + xMult*log((buffer[0][a]-buffer[1][a])+1); // making Lissajous plot vertical instead of angled 145 | int yPhaseOffset = mRECT.B - yPos - yMult*log(buffer[1][a]+1); 146 | int xPhaseOffset2 = mRECT.L + xPos + xMult*log((buffer[0][a+1]-buffer[1][a+1])+1); // making Lissajous plot vertical instead of angled 147 | int yPhaseOffset2 = mRECT.B - yPos - yMult*log(buffer[1][a+1]+1); 148 | 149 | // points 150 | LICE_PutPixel(pGraphics->GetDrawBitmap(), xPhaseOffset, yPhaseOffset, pixGreen, 0.4, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 151 | LICE_PutPixel(pGraphics->GetDrawBitmap(), xPhaseOffset-1, yPhaseOffset, pixGreen, 0.2, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 152 | LICE_PutPixel(pGraphics->GetDrawBitmap(), xPhaseOffset+1, yPhaseOffset, pixGreen, 0.2, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 153 | LICE_PutPixel(pGraphics->GetDrawBitmap(), xPhaseOffset, yPhaseOffset-1, pixGreen, 0.2, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 154 | LICE_PutPixel(pGraphics->GetDrawBitmap(), xPhaseOffset, yPhaseOffset+1, pixGreen, 0.2, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 155 | 156 | // lines 157 | LICE_Line(pGraphics->GetDrawBitmap(), xPhaseOffset, yPhaseOffset, xPhaseOffset2, yPhaseOffset2, pixGreen, 0.1, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 158 | 159 | } 160 | 161 | 162 | 163 | 164 | /// bezier 165 | 166 | // for (int a = 0; a < bufferSize - 2; a+=2) { 167 | // 168 | // x = a; 169 | // xOffset = mRECT.L + x + 50; 170 | // yOffset = mRECT.B - 150 - 1000*buffer[0][a]; 171 | // yOffsetNext = mRECT.B - 150 - 1000*buffer[0][a+1]; 172 | // yOffsetEnd = mRECT.B - 150 - 1000*buffer[0][a+2]; 173 | // 174 | // LICE_DrawQBezier(pGraphics->GetDrawBitmap(), xOffset, yOffset, xOffset+1, yOffsetNext, xOffset+2, yOffsetEnd, pixLightGreen, 0.4, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 175 | // LICE_DrawQBezier(pGraphics->GetDrawBitmap(), xOffset, yOffset+1, xOffset+1, yOffsetNext+1, xOffset+2, yOffsetEnd+1, pixGreen, 0.4, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 176 | // LICE_DrawQBezier(pGraphics->GetDrawBitmap(), xOffset, yOffset-1, xOffset+1, yOffsetNext-1, xOffset+2, yOffsetEnd-1, pixGreen, 0.4, LICE_BLIT_USE_ALPHA | LICE_BLIT_MODE_ADD); 177 | // 178 | // } 179 | 180 | 181 | 182 | 183 | 184 | return true; 185 | } 186 | 187 | bool Oscilloscope::IsDirty() { 188 | return true; 189 | } 190 | -------------------------------------------------------------------------------- /Oscilloscope.h: -------------------------------------------------------------------------------- 1 | // 2 | // Oscilloscope.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/16/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__Oscilloscope__ 10 | #define __Synthesis__Oscilloscope__ 11 | 12 | //#ifdef OS_OSX 13 | #include 14 | #include 15 | #include 16 | #include 17 | #pragma clang diagnostic push 18 | #pragma clang diagnostic ignored "-Wextra-tokens" 19 | #include "IPlug_include_in_plug_hdr.h" 20 | #pragma clang diagnostic pop 21 | #include "IControl.h" 22 | #include 23 | 24 | 25 | 26 | class Oscilloscope : public IControl { 27 | 28 | public: 29 | Oscilloscope(IPlugBase* pPlug, IRECT pR) : 30 | IControl(pPlug, pR, -1), 31 | bufferSize(1764), // works pretty well with 98 and % 18, or 196/9 32 | mLastSample(0.0), 33 | xPos(1), 34 | xOffset(0), 35 | yOffset(0), 36 | yOffsetNext(0), 37 | yOffsetEnd(0), 38 | //cb(cbSize), // as many elements in ring buffer as there are pixels in width of oscilloscope 39 | rgbR(55), 40 | rgbG(255), 41 | rgbB(55), 42 | iterator(0), 43 | bufferFull(false) 44 | //width(300), 45 | //height(300) 46 | //xMultiplier(OSCILLOSCOPE_WIDTH / cbSize) 47 | { 48 | initBuffer(); 49 | createContext(); 50 | //mData.Resize(mRECT.W() * mRECT.H() * 4); 51 | updatePixelColors(); 52 | } 53 | 54 | ~Oscilloscope() { 55 | destroyContext(); 56 | } 57 | 58 | void updateLastSample(double sampleL, double sampleR); 59 | long setContext(); 60 | void restoreContext(); 61 | long createContext(); 62 | void destroyContext(); 63 | bool Draw(IGraphics* pGraphics); 64 | bool IsDirty(); 65 | double mLastSample; 66 | void updatePixelColors(); 67 | 68 | private: 69 | CGLContextObj mGLContext; 70 | WDL_TypedBuf mData; 71 | float mRotateTri, mRotateQuad; 72 | int xPos; 73 | int halfHeight; 74 | int xOffset; 75 | int yOffset; 76 | int yOffsetNext; 77 | int yOffsetEnd; 78 | int rgbR; 79 | int rgbG; 80 | int rgbB; 81 | int x; 82 | const int bufferSize; 83 | //int width; 84 | //int height; 85 | //double xMultiplier; 86 | //boost::circular_buffer cb; 87 | double buffer [2][1764]; 88 | bool bufferFull; 89 | int iterator; 90 | void initBuffer(); 91 | LICE_pixel pixBlack; 92 | LICE_pixel pixGreen; 93 | LICE_pixel pixLightGreen; 94 | LICE_pixel pixWhite; 95 | }; 96 | //#endif 97 | 98 | 99 | #endif /* defined(__Synthesis__Oscilloscope__) */ 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gpu-synth 2 | by Devin Mooers 3 | 4 | This is an OpenCL-powered additive synthesizer plugin. It's meant to run on a beefy GPU. 5 | 6 | The OpenCL synthesis code is inside `opencl_kernels.cl`. The OpenCL handler code is in `OpenCL.cpp` - this writes/reads OpenCL buffers to/from the kernel/GPU. `VoiceManager.cpp` handles voice management and setting the energy and damping parameters of each voice (which then get fed > OpenCL.cpp > opencl_kernels.cl for synthesis). 7 | 8 | gpu-synth uses the WDL-OL plugin framework by Oli Larkin. 9 | 10 | #### Warning: this is probably completely broken. Just FYI! This is not plug-and-play. Feel free to gut the code, though, and use it for your own purposes. 11 | 12 | License: MIT. Credit appreciated! -------------------------------------------------------------------------------- /Synthesis-aax.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {ed0eb9dd-b586-4a3f-98af-ebd9c084fff2} 6 | 7 | 8 | {a484aa50-ad02-4746-957e-117c8bb5c192} 9 | 10 | 11 | {57d1624e-a679-47da-bd3e-9609f02fdd7b} 12 | 13 | 14 | 15 | 16 | IPlug 17 | 18 | 19 | IPlug 20 | 21 | 22 | IPlug 23 | 24 | 25 | IPlug 26 | 27 | 28 | IPlug 29 | 30 | 31 | IPlug 32 | 33 | 34 | IPlug 35 | 36 | 37 | IPlug 38 | 39 | 40 | IPlug 41 | 42 | 43 | IPlug 44 | 45 | 46 | IPlug\AAX 47 | 48 | 49 | IPlug\AAX 50 | 51 | 52 | IPlug\AAX 53 | 54 | 55 | 56 | Libs 57 | 58 | 59 | 60 | 61 | IPlug 62 | 63 | 64 | IPlug 65 | 66 | 67 | IPlug 68 | 69 | 70 | IPlug 71 | 72 | 73 | IPlug 74 | 75 | 76 | IPlug 77 | 78 | 79 | IPlug 80 | 81 | 82 | IPlug 83 | 84 | 85 | IPlug 86 | 87 | 88 | IPlug 89 | 90 | 91 | IPlug 92 | 93 | 94 | IPlug 95 | 96 | 97 | IPlug 98 | 99 | 100 | IPlug 101 | 102 | 103 | IPlug 104 | 105 | 106 | IPlug 107 | 108 | 109 | IPlug\AAX 110 | 111 | 112 | IPlug\AAX 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Libs 123 | 124 | 125 | Libs 126 | 127 | 128 | Libs 129 | 130 | 131 | Libs 132 | 133 | 134 | -------------------------------------------------------------------------------- /Synthesis-app.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {6a6c24bd-7110-4436-97af-07990da17abf} 6 | 7 | 8 | {ef87c677-1479-44bc-aef8-7ba960ef233d} 9 | 10 | 11 | {b91b9db4-5584-4959-a395-7394ba3cf5a3} 12 | 13 | 14 | 15 | 16 | app\RtAudioMidi 17 | 18 | 19 | app\RtAudioMidi 20 | 21 | 22 | app\RtAudioMidi 23 | 24 | 25 | app\ASIO_SDK 26 | 27 | 28 | app\ASIO_SDK 29 | 30 | 31 | app\ASIO_SDK 32 | 33 | 34 | app\ASIO_SDK 35 | 36 | 37 | app\ASIO_SDK 38 | 39 | 40 | app\ASIO_SDK 41 | 42 | 43 | app 44 | 45 | 46 | 47 | 48 | app 49 | 50 | 51 | 52 | 53 | 54 | app\RtAudioMidi 55 | 56 | 57 | app\RtAudioMidi 58 | 59 | 60 | app\ASIO_SDK 61 | 62 | 63 | app\ASIO_SDK 64 | 65 | 66 | app\ASIO_SDK 67 | 68 | 69 | app 70 | 71 | 72 | app 73 | 74 | 75 | 76 | app 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /Synthesis-rtas.def: -------------------------------------------------------------------------------- 1 | LIBRARY Synthesis 2 | EXPORTS 3 | NewPlugIn @1 4 | _PI_GetRoutineDescriptor @2 -------------------------------------------------------------------------------- /Synthesis-rtas.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {73d47a52-ce2f-4264-9bb9-f0b3c16f889d} 6 | 7 | 8 | {f61218de-bb49-4fd2-b3b8-d4d3a4f905de} 9 | 10 | 11 | {f55aca3b-4b35-490a-99d6-51d6724f0396} 12 | 13 | 14 | {13073ee3-c4e8-497c-b935-b091b14197c2} 15 | 16 | 17 | 18 | 19 | Libs 20 | 21 | 22 | Libs 23 | 24 | 25 | Libs 26 | 27 | 28 | Libs 29 | 30 | 31 | Libs 32 | 33 | 34 | Libs 35 | 36 | 37 | Libs 38 | 39 | 40 | 41 | 42 | IPlug 43 | 44 | 45 | IPlug 46 | 47 | 48 | IPlug 49 | 50 | 51 | IPlug 52 | 53 | 54 | IPlug 55 | 56 | 57 | IPlug 58 | 59 | 60 | IPlug 61 | 62 | 63 | IPlug 64 | 65 | 66 | IPlug 67 | 68 | 69 | IPlug 70 | 71 | 72 | IPlug 73 | 74 | 75 | IPlug 76 | 77 | 78 | IPlug 79 | 80 | 81 | IPlug 82 | 83 | 84 | IPlug 85 | 86 | 87 | IPlug 88 | 89 | 90 | IPlug 91 | 92 | 93 | IPlug\RTAS 94 | 95 | 96 | IPlug\RTAS 97 | 98 | 99 | IPlug\RTAS 100 | 101 | 102 | IPlug\RTAS 103 | 104 | 105 | IPlug\RTAS 106 | 107 | 108 | IPlug\RTAS 109 | 110 | 111 | IPlug\RTAS 112 | 113 | 114 | IPlug\RTAS\include 115 | 116 | 117 | 118 | 119 | IPlug\RTAS 120 | 121 | 122 | 123 | 124 | IPlug 125 | 126 | 127 | IPlug 128 | 129 | 130 | IPlug 131 | 132 | 133 | IPlug 134 | 135 | 136 | IPlug 137 | 138 | 139 | IPlug 140 | 141 | 142 | IPlug 143 | 144 | 145 | IPlug 146 | 147 | 148 | IPlug 149 | 150 | 151 | IPlug 152 | 153 | 154 | IPlug 155 | 156 | 157 | IPlug\RTAS 158 | 159 | 160 | IPlug\RTAS 161 | 162 | 163 | IPlug\RTAS 164 | 165 | 166 | IPlug\RTAS 167 | 168 | 169 | IPlug\RTAS\include 170 | 171 | 172 | IPlug\RTAS\include 173 | 174 | 175 | IPlug\RTAS\include 176 | 177 | 178 | 179 | IPlug\RTAS 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /Synthesis-vst2.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 | Tracer 22 | Win32 23 | 24 | 25 | Tracer 26 | x64 27 | 28 | 29 | 30 | {2EB4846A-93E0-43A0-821E-12237105168F} 31 | Synthesis 32 | Synthesis-vst2 33 | 34 | 35 | 36 | DynamicLibrary 37 | true 38 | MultiByte 39 | 40 | 41 | DynamicLibrary 42 | true 43 | MultiByte 44 | 45 | 46 | DynamicLibrary 47 | false 48 | true 49 | MultiByte 50 | 51 | 52 | DynamicLibrary 53 | false 54 | true 55 | MultiByte 56 | 57 | 58 | DynamicLibrary 59 | false 60 | true 61 | MultiByte 62 | 63 | 64 | DynamicLibrary 65 | false 66 | true 67 | MultiByte 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | build-win\vst2\$(Platform)\bin\ 99 | 100 | 101 | build-win\vst2\$(Platform)\bin\ 102 | 103 | 104 | build-win\vst2\$(Platform)\$(Configuration)\ 105 | 106 | 107 | 108 | 109 | build-win\vst2\$(Platform)\$(Configuration)\ 110 | 111 | 112 | 113 | build-win\vst2\$(Platform)\bin\ 114 | 115 | 116 | build-win\vst2\$(Platform)\bin\ 117 | 118 | 119 | build-win\vst2\$(Platform)\$(Configuration)\ 120 | 121 | 122 | build-win\vst2\$(Platform)\$(Configuration)\ 123 | 124 | 125 | build-win\vst2\$(Platform)\bin\ 126 | 127 | 128 | build-win\vst2\$(Platform)\bin\ 129 | 130 | 131 | build-win\vst2\$(Platform)\$(Configuration)\ 132 | 133 | 134 | build-win\vst2\$(Platform)\$(Configuration)\ 135 | 136 | 137 | 138 | Level3 139 | Disabled 140 | $(VST_DEFS);$(DEBUG_DEFS);%(PreprocessorDefinitions) 141 | MultiThreadedDebug 142 | 143 | 144 | true 145 | Windows 146 | 147 | 148 | 149 | 150 | Level3 151 | Disabled 152 | $(VST_DEFS);$(DEBUG_DEFS);%(PreprocessorDefinitions) 153 | MultiThreadedDebug 154 | 155 | 156 | true 157 | Windows 158 | $(x64_LIB_PATHS);%(AdditionalLibraryDirectories) 159 | 160 | 161 | 162 | 163 | Level3 164 | MaxSpeed 165 | true 166 | true 167 | $(VST_DEFS);$(RELEASE_DEFS);%(PreprocessorDefinitions) 168 | true 169 | Speed 170 | 171 | 172 | true 173 | true 174 | true 175 | Windows 176 | 177 | 178 | 179 | 180 | Level3 181 | MaxSpeed 182 | true 183 | true 184 | $(VST_DEFS);$(RELEASE_DEFS);%(PreprocessorDefinitions) 185 | true 186 | Speed 187 | 188 | 189 | true 190 | true 191 | true 192 | Windows 193 | $(x64_LIB_PATHS);%(AdditionalLibraryDirectories) 194 | 195 | 196 | 197 | 198 | Level3 199 | MaxSpeed 200 | true 201 | true 202 | $(VST_DEFS);$(TRACER_DEFS);%(PreprocessorDefinitions) 203 | true 204 | 205 | 206 | true 207 | true 208 | true 209 | Windows 210 | $(WDL_PATH)\lice\build-win\$(Platform)\Release\;%(AdditionalLibraryDirectories) 211 | 212 | 213 | 214 | 215 | Level3 216 | MaxSpeed 217 | true 218 | true 219 | $(VST_DEFS);$(TRACER_DEFS);%(PreprocessorDefinitions) 220 | true 221 | 222 | 223 | true 224 | true 225 | true 226 | Windows 227 | $(x64_LIB_PATHS);$(WDL_PATH)\lice\build-win\$(Platform)\Release\;%(AdditionalLibraryDirectories) 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | -------------------------------------------------------------------------------- /Synthesis-vst2.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | vst2 7 | 8 | 9 | 10 | 11 | 12 | 13 | vst2 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {ea16de74-9d15-4c60-ba09-d0924088d3e5} 22 | 23 | 24 | -------------------------------------------------------------------------------- /Synthesis-vst2.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(TargetPath) /noload /nosave 5 | 6 | 7 | $(TargetDir) 8 | WindowsLocalDebugger 9 | $(VST2_32_HOST_PATH) 10 | 11 | 12 | $(TargetPath) /noload /nosave 13 | WindowsLocalDebugger 14 | $(TargetDir) 15 | $(VST2_32_HOST_PATH) 16 | 17 | 18 | $(TargetPath) /noload /nosave 19 | WindowsLocalDebugger 20 | $(TargetDir) 21 | $(VST2_32_HOST_PATH) 22 | 23 | 24 | $(TargetDir) 25 | WindowsLocalDebugger 26 | $(TargetPath) /noload /nosave 27 | $(VST2_64_HOST_PATH) 28 | 29 | 30 | $(TargetDir) 31 | WindowsLocalDebugger 32 | $(TargetPath) /noload /nosave 33 | $(VST2_64_HOST_PATH) 34 | 35 | 36 | $(TargetDir) 37 | WindowsLocalDebugger 38 | $(TargetPath) /noload /nosave 39 | $(VST2_64_HOST_PATH) 40 | 41 | -------------------------------------------------------------------------------- /Synthesis-vst3.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | vst3\VST3SDK\pluginterfaces\base 7 | 8 | 9 | vst3\VST3SDK\pluginterfaces\base 10 | 11 | 12 | vst3\VST3SDK\public.sdk\common 13 | 14 | 15 | vst3\VST3SDK\public.sdk\vst 16 | 17 | 18 | vst3\VST3SDK\public.sdk\vst 19 | 20 | 21 | vst3\VST3SDK\public.sdk\vst 22 | 23 | 24 | vst3\VST3SDK\public.sdk\vst 25 | 26 | 27 | vst3\VST3SDK\public.sdk\vst 28 | 29 | 30 | vst3\VST3SDK\public.sdk\vst 31 | 32 | 33 | vst3\VST3SDK\public.sdk\main 34 | 35 | 36 | vst3\VST3SDK\public.sdk\main 37 | 38 | 39 | vst3\VST3SDK\public.sdk\vst 40 | 41 | 42 | vst3 43 | 44 | 45 | 46 | 47 | 48 | 49 | vst3\VST3SDK\pluginterfaces\base 50 | 51 | 52 | vst3\VST3SDK\pluginterfaces\base 53 | 54 | 55 | vst3\VST3SDK\pluginterfaces\base 56 | 57 | 58 | vst3\VST3SDK\pluginterfaces\base 59 | 60 | 61 | vst3\VST3SDK\pluginterfaces\base 62 | 63 | 64 | vst3\VST3SDK\pluginterfaces\base 65 | 66 | 67 | vst3\VST3SDK\pluginterfaces\base 68 | 69 | 70 | vst3\VST3SDK\pluginterfaces\base 71 | 72 | 73 | vst3\VST3SDK\pluginterfaces\vst 74 | 75 | 76 | vst3\VST3SDK\pluginterfaces\vst 77 | 78 | 79 | vst3\VST3SDK\pluginterfaces\vst 80 | 81 | 82 | vst3\VST3SDK\pluginterfaces\vst 83 | 84 | 85 | vst3\VST3SDK\pluginterfaces\vst 86 | 87 | 88 | vst3\VST3SDK\pluginterfaces\vst 89 | 90 | 91 | vst3\VST3SDK\pluginterfaces\vst 92 | 93 | 94 | vst3\VST3SDK\pluginterfaces\vst 95 | 96 | 97 | vst3\VST3SDK\pluginterfaces\vst 98 | 99 | 100 | vst3\VST3SDK\pluginterfaces\vst 101 | 102 | 103 | vst3\VST3SDK\pluginterfaces\vst 104 | 105 | 106 | vst3\VST3SDK\pluginterfaces\vst 107 | 108 | 109 | vst3\VST3SDK\pluginterfaces\vst 110 | 111 | 112 | vst3\VST3SDK\pluginterfaces\gui 113 | 114 | 115 | vst3\VST3SDK\public.sdk\common 116 | 117 | 118 | vst3\VST3SDK\public.sdk\vst 119 | 120 | 121 | vst3\VST3SDK\public.sdk\vst 122 | 123 | 124 | vst3\VST3SDK\public.sdk\vst 125 | 126 | 127 | vst3\VST3SDK\public.sdk\vst 128 | 129 | 130 | vst3\VST3SDK\public.sdk\vst 131 | 132 | 133 | vst3\VST3SDK\public.sdk\vst 134 | 135 | 136 | vst3\VST3SDK\public.sdk\main 137 | 138 | 139 | vst3\VST3SDK\public.sdk\vst 140 | 141 | 142 | vst3 143 | 144 | 145 | 146 | 147 | {0028f8fa-40ce-4098-b1d7-1930d1a7774b} 148 | 149 | 150 | {d33dc1fa-0b31-40b9-a240-b065db740979} 151 | 152 | 153 | {1da1c979-a505-4558-b877-1a2da0e4e758} 154 | 155 | 156 | {cf0c95d2-7b5a-4afa-8a3e-546800d9b337} 157 | 158 | 159 | {babb4a18-d1d6-467e-af1c-fb852400f591} 160 | 161 | 162 | {a0598a21-18c6-4da8-98a8-bebbf0f37b34} 163 | 164 | 165 | {bc78847c-a41c-4ad7-8a8e-2ea825bc2f8e} 166 | 167 | 168 | {23863805-5085-4669-8675-167aba1f0fc9} 169 | 170 | 171 | {00ff2592-e5ef-4ab1-8b06-c42242d80c52} 172 | 173 | 174 | {ec7b025c-4ef1-4403-956b-b3673b4715b8} 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /Synthesis-vst3.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(VST3_32_HOST_PATH) 5 | WindowsLocalDebugger 6 | $(TargetPath) 7 | $(TargetDir) 8 | 9 | 10 | $(VST3_32_HOST_PATH) 11 | WindowsLocalDebugger 12 | $(TargetPath) 13 | $(TargetDir) 14 | 15 | 16 | $(VST3_32_HOST_PATH) 17 | WindowsLocalDebugger 18 | $(TargetPath) 19 | $(TargetDir) 20 | 21 | 22 | $(TargetPath) 23 | 24 | 25 | $(TargetDir) 26 | WindowsLocalDebugger 27 | $(VST3_64_HOST_PATH) 28 | 29 | 30 | $(TargetPath) 31 | 32 | 33 | $(TargetDir) 34 | WindowsLocalDebugger 35 | 36 | 37 | $(TargetPath) 38 | 39 | 40 | $(TargetDir) 41 | WindowsLocalDebugger 42 | 43 | -------------------------------------------------------------------------------- /Synthesis.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 250 | 251 | -------------------------------------------------------------------------------- /Synthesis.cpp: -------------------------------------------------------------------------------- 1 | #include "Synthesis.h" 2 | #pragma clang diagnostic push 3 | #pragma clang diagnostic ignored "-Wmain" 4 | #pragma clang diagnostic ignored "-Wint-to-pointer-cast" 5 | #include "IPlug_include_in_plug_src.h" 6 | #pragma clang diagnostic pop 7 | #include "IControl.h" 8 | #include "IPlugMultiTargets_controls.h" 9 | #include "IKeyboardControl.h" 10 | #include "resource.h" 11 | 12 | const int kNumPrograms = 5; // number of presets to include (will fill with "Empty" if not enough presets are declared below) 13 | const double parameterStep = 0.001; 14 | enum EParams 15 | { 16 | mB, 17 | mNumPartials, 18 | mStringDetuneRange, 19 | mPartialDetuneRange, 20 | mDamping, 21 | mLinearTerm, 22 | mSquaredTerm, 23 | mCubicTerm, 24 | mBrightnessA, 25 | mBrightnessB, 26 | mPitchBendCoarse, 27 | mPitchBendFine, 28 | //mNoisyTransient, 29 | kNumParams 30 | }; 31 | 32 | typedef struct { 33 | const char* name; 34 | const int x1; 35 | const int y1; 36 | const int x2; 37 | const int y2; 38 | const double defaultVal; 39 | const double minVal; 40 | const double maxVal; 41 | const double step; 42 | /// also need a shape parameter in here! 43 | } parameterProperties_struct; 44 | 45 | 46 | const parameterProperties_struct parameterProperties[kNumParams] = 47 | { 48 | { 49 | .name="Inharmonicity", 50 | .x1 = 50, 51 | .y1 = 100, 52 | .x2 = 50+60, 53 | .y2 = 100+90, 54 | .defaultVal = 0.003, 55 | .minVal = 0.0, 56 | .maxVal = 1.0, 57 | .step = 0.0001 58 | }, 59 | { 60 | .name="Partials", 61 | .x1 = 150, 62 | .y1 = 50, 63 | .x2 = 150+60, 64 | .y2 = 50+90 65 | }, 66 | { 67 | .name="String Detune Range", 68 | .x1 = 250, 69 | .y1 = 100, 70 | .x2 = 250+60, 71 | .y2 = 100+90, 72 | .defaultVal = 0.001, 73 | .minVal = 0.0001, 74 | .maxVal = 0.01, 75 | .step = 0.0001 76 | }, 77 | { 78 | .name="Partial Detune Range", 79 | .x1 = 350, 80 | .y1 = 50, 81 | .x2 = 350+60, 82 | .y2 = 50+90, 83 | .defaultVal = 1.0, 84 | .minVal = 0.1, 85 | .maxVal = 2.0, 86 | .step = 0.001 87 | }, 88 | { 89 | .name="Damping", 90 | .x1 = 450, 91 | .y1 = 100, 92 | .x2 = 450+60, 93 | .y2 = 100+90, 94 | .defaultVal = 2.5, 95 | .minVal = 0.1, 96 | .maxVal = 10.0, 97 | .step = 0.001 98 | }, 99 | { 100 | .name="Linear Term", 101 | .x1 = 50, 102 | .y1 = 250, 103 | .x2 = 50+60, 104 | .y2 = 250+90, 105 | .defaultVal = 0.3, 106 | .minVal = 0.001, 107 | .maxVal = 1.0, 108 | .step = 0.001 109 | }, 110 | { 111 | .name="Squared Term", 112 | .x1 = 150, 113 | .y1 = 200, 114 | .x2 = 150+60, 115 | .y2 = 200+90, 116 | .defaultVal = 1.0, 117 | .minVal = 0.001, 118 | .maxVal = 1.0, 119 | .step = 0.001 120 | }, 121 | { 122 | .name="Cubic Term", 123 | .x1 = 250, 124 | .y1 = 250, 125 | .x2 = 250+60, 126 | .y2 = 250+90, 127 | .defaultVal = 0.3, 128 | .minVal = 0.001, 129 | .maxVal = 1.0, 130 | .step = 0.001 131 | }, 132 | { 133 | .name="Brightness A", 134 | .x1 = 350, 135 | .y1 = 200, 136 | .x2 = 350+60, 137 | .y2 = 200+90, 138 | .defaultVal = 0.4, 139 | .minVal = 0.001, 140 | .maxVal = 1.0, 141 | .step = 0.001 142 | }, 143 | { 144 | .name="Brightness B", 145 | .x1 = 450, 146 | .y1 = 250, 147 | .x2 = 450+60, 148 | .y2 = 250+90, 149 | .defaultVal = 0.2, 150 | .minVal = 0.001, 151 | .maxVal = 1.0, 152 | .step = 0.001 153 | }, 154 | { 155 | .name="Pitch Bend Coarse", 156 | .x1 = 50, 157 | .y1 = 350, 158 | .x2 = 50+60, 159 | .y2 = 350+90, 160 | .defaultVal = 0.5, 161 | .minVal = 0.001, 162 | .maxVal = 1.0, 163 | .step = 0.001 164 | }, 165 | { 166 | .name="Pitch Bend Fine", 167 | .x1 = 150, 168 | .y1 = 350, 169 | .x2 = 150+60, 170 | .y2 = 350+90, 171 | .defaultVal = 0.5, 172 | .minVal = 0.001, 173 | .maxVal = 1.0, 174 | .step = 0.001 175 | } 176 | // { 177 | // .name="Noisy Transient", 178 | // .x1 = 50, 179 | // .y1 = 374, 180 | // .x2 = 50+60, 181 | // .y2 = 374+90 182 | // } 183 | }; 184 | 185 | enum ELayout 186 | { 187 | kWidth = GUI_WIDTH, 188 | kHeight = GUI_HEIGHT, 189 | kKeybX = 1, 190 | kKeybY = 720 191 | 192 | //kFrequencyX = 79, 193 | //kFrequencyY = 62, 194 | //kKnobFrames = 128 195 | }; 196 | 197 | Synthesis::Synthesis(IPlugInstanceInfo instanceInfo) 198 | : IPLUG_CTOR(kNumParams, kNumPrograms, instanceInfo), 199 | lastVirtualKeyboardNoteNumber(virtualKeyboardMinimumNoteNumber - 1) 200 | { 201 | TRACE; 202 | 203 | CreateParams(); 204 | CreateGraphics(); 205 | CreatePresets(); 206 | 207 | VoiceManager& voiceManager = VoiceManager::getInstance(); 208 | voiceManager.initOpenCL(); 209 | 210 | //openCLStarted = false; 211 | 212 | // connet the noteOn's and noteOff's from mMIDIReceiver to VoiceManager using signals and slots 213 | mMIDIReceiver.noteOn.Connect(&voiceManager, &VoiceManager::onNoteOn); 214 | mMIDIReceiver.noteOff.Connect(&voiceManager, &VoiceManager::onNoteOff); 215 | mMIDIReceiver.sustainChange.Connect(&voiceManager, &VoiceManager::onSustainChange); 216 | mMIDIReceiver.expressionChange.Connect(&voiceManager, &VoiceManager::onExpressionChange); 217 | mMIDIReceiver.modChange.Connect(&voiceManager, &VoiceManager::onModChange); 218 | //mMIDIReceiver.noteOn.Connect(mOscilloscope, &Oscilloscope::updatePixelColors); 219 | } 220 | 221 | Synthesis::~Synthesis() {} 222 | 223 | void Synthesis::CreateParams() { 224 | for (int i = 0; i < kNumParams; i++) { 225 | IParam* param = GetParam(i); 226 | const parameterProperties_struct& properties = parameterProperties[i]; 227 | switch (i) { 228 | // Int parameters: 229 | case mNumPartials: 230 | param->InitInt(properties.name, 231 | 10, // default 232 | 1, // min 233 | 200); // max 234 | break; 235 | // Bool parameters: 236 | // case mNoisyTransient: 237 | // param->InitBool(properties.name, true); 238 | // break; 239 | // Double parameters: 240 | default: 241 | param->InitDouble(properties.name, 242 | properties.defaultVal, 243 | properties.minVal, 244 | properties.maxVal, 245 | parameterStep); 246 | break; 247 | } 248 | } 249 | 250 | /// set shape for knobs 251 | GetParam(mB)->SetShape(5); 252 | GetParam(mNumPartials)->SetShape(1); 253 | 254 | /// initialize correct default parameter values on load 255 | for (int i = 0; i < kNumParams; i++) { 256 | OnParamChange(i); 257 | } 258 | } 259 | 260 | void Synthesis::CreateGraphics() { 261 | 262 | IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight); 263 | pGraphics->AttachPanelBackground(&COLOR_BLACK); 264 | //pGraphics->AttachBackground(BG_ID, BG_FN); 265 | 266 | IBitmap whiteKeyImage = pGraphics->LoadIBitmap(WHITE_KEY_ID, WHITE_KEY_FN, 6); 267 | IBitmap blackKeyImage = pGraphics->LoadIBitmap(BLACK_KEY_ID, BLACK_KEY_FN); 268 | 269 | //mOscilloscope = new Oscilloscope(this, IRECT(0, 300, GUI_WIDTH, GUI_HEIGHT)); 270 | 271 | // C# D# F# G# A# 272 | int keyCoordinates[12] = { 0, 10, 17, 30, 35, 52, 61, 68, 79, 85, 97, 102 }; 273 | 274 | mVirtualKeyboard = new IKeyboardControl(this, kKeybX, kKeybY, virtualKeyboardMinimumNoteNumber, /* octaves: */ 8, &whiteKeyImage, &blackKeyImage, keyCoordinates); 275 | 276 | pGraphics->AttachControl(mVirtualKeyboard); 277 | 278 | // Knob bitmap 279 | IBitmap knobBitmap = pGraphics->LoadIBitmap(KNOB_ID, KNOB_FN, 101); 280 | 281 | for (int i = 0; i < kNumParams; i++) { 282 | const parameterProperties_struct& properties = parameterProperties[i]; 283 | IControl* control; 284 | IControl* labelcontrol; 285 | IBitmap* graphic; 286 | IText text = IText(14, &COLOR_WHITE); 287 | IText labeltext = IText(14, &COLOR_WHITE); 288 | 289 | switch (i) { 290 | // Knobs: 291 | default: 292 | graphic = &knobBitmap; 293 | control = new IKnobMultiControlText(this, IRECT(properties.x1, properties.y1, properties.x2, properties.y2), i, graphic, &text); 294 | labelcontrol = new ITextControl(this, IRECT(properties.x1, properties.y1-20, properties.x2, properties.y1), &labeltext, properties.name); 295 | break; 296 | } 297 | pGraphics->AttachControl(control); 298 | pGraphics->AttachControl(labelcontrol); 299 | } 300 | 301 | 302 | 303 | // // caption 304 | // IText mBLabel(14, &COLOR_WHITE); 305 | // pGraphics->AttachControl(new ITextControl(this, IRECT(60-12, 154-20, 60+50, 154+20), &mBLabel, "Inharmonicity")); 306 | // 307 | 308 | 309 | // // TEXT TESTING 310 | // 311 | // IRECT tmpRect4(650, 50, 800, 120); 312 | // IText textProps4(40, &COLOR_WHITE, "Helvetica", IText::kStyleNormal, IText::kAlignCenter, 0, IText::kQualityDefault); 313 | // pGraphics->AttachControl(new ITextControl(this, tmpRect4, &textProps4, "STRING SYNTH")); 314 | 315 | 316 | 317 | //pGraphics->AttachControl(mOscilloscope); 318 | 319 | AttachGraphics(pGraphics); 320 | } 321 | 322 | 323 | ///////////////////////////---------//////////////////////////// 324 | 325 | void Synthesis::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames) 326 | { 327 | // Mutex is already locked for us. 328 | 329 | double *leftOutput = outputs[0]; 330 | double *rightOutput = outputs[1]; 331 | VoiceManager& voiceManager = VoiceManager::getInstance(); 332 | processVirtualKeyboard(); 333 | 334 | 335 | 336 | 337 | //std::cout << "\nBlock size = " << GetBlockSize(); 338 | 339 | 340 | // blockOfSamples = voiceManager.getBlockOfSamples(); 341 | // for (int i = 0; i < BLOCK_SIZE; i++) { 342 | // leftOutput[i] = blockOfSamples[i*NUM_CHANNELS]; 343 | // rightOutput[i] = blockOfSamples[i*NUM_CHANNELS + 1]; 344 | //// if (i < 512) { 345 | //// printf("\ni = %d, left = %f, right = %f", i, leftOutput[i], rightOutput[i]); 346 | //// } 347 | // //printf("\nleftOutput index = %d, rightOutput index = %d", i*NUM_CHANNELS, i*NUM_CHANNELS+1); 348 | // mOscilloscope->updateLastSample(leftOutput[i], rightOutput[i]); 349 | // mMIDIReceiver.advance(); 350 | // } 351 | 352 | //std::thread voiceEnergyUpdater(&Synthesis::voiceEnergyUpdaterManager, this); 353 | 354 | 355 | /// this allows for BLOCK_SIZE to be different (smaller) than actual VST host blockSize, to reduce latency 356 | int numBlocks = nFrames/BLOCK_SIZE; 357 | 358 | 359 | for (int j = 0; j < numBlocks; j++) { 360 | 361 | blockOfSamples = voiceManager.getBlockOfSamples(); 362 | for (int i = 0; i < BLOCK_SIZE; i++) { 363 | 364 | leftOutput[i + j*BLOCK_SIZE] = clip(blockOfSamples[i*NUM_CHANNELS]); 365 | rightOutput[i + j*BLOCK_SIZE] = clip(blockOfSamples[i*NUM_CHANNELS + 1]); 366 | 367 | // add in bandlimited noise 368 | // leftOutput[i + j*BLOCK_SIZE] += 0.003f * (static_cast (rand()) /( static_cast (RAND_MAX/2.0f)) - 1.0f) * blockOfSamples[i*NUM_CHANNELS]; 369 | // rightOutput[i + j*BLOCK_SIZE] += 0.003f * (static_cast (rand()) /( static_cast (RAND_MAX/2.0f)) - 1.0f) * blockOfSamples[i*NUM_CHANNELS + 1]; 370 | 371 | 372 | // mOscilloscope->updateLastSample(leftOutput[i], rightOutput[i]); 373 | mMIDIReceiver.advance(); 374 | voiceManager.updateVoiceDampingAndEnergy(i); 375 | } 376 | mMIDIReceiver.Flush(nFrames/numBlocks); 377 | voiceManager.setFreeInaudibleVoices(); 378 | } 379 | 380 | 381 | 382 | 383 | // for (int i = 0; i < nFrames/BLOCK_SIZE; i++) { 384 | // blockOfSamples = voiceManager.getBlockOfSamples(); 385 | // for (int j = 0; j < BLOCK_SIZE; j++) { 386 | // leftOutput[i*BLOCK_SIZE + j] = blockOfSamples[i*NUM_CHANNELS]; 387 | // rightOutput[i*BLOCK_SIZE + j] = blockOfSamples[i*NUM_CHANNELS + 1]; 388 | // mOscilloscope->updateLastSample(leftOutput[i], rightOutput[i]); 389 | // mMIDIReceiver.advance(); 390 | // } 391 | // } 392 | 393 | //mMIDIReceiver.Flush(nFrames); 394 | } 395 | 396 | double Synthesis::clip(double n) { 397 | return std::max(-0.99, std::min(n, 0.99)); 398 | } 399 | 400 | 401 | ///////////////////////////---------//////////////////////////// 402 | 403 | 404 | 405 | 406 | 407 | void Synthesis::Reset() 408 | { 409 | TRACE; 410 | IMutexLock lock(this); 411 | double sampleRate = GetSampleRate(); 412 | VoiceManager::getInstance().setSampleRate(sampleRate); 413 | } 414 | 415 | void Synthesis::OnParamChange(int paramIdx) 416 | { 417 | IMutexLock lock(this); 418 | VoiceManager& voiceManager = VoiceManager::getInstance(); 419 | IParam* param = GetParam(paramIdx); 420 | // std::cout << paramIdx << "\n"; 421 | // printf("\nparam: %s", paramIdx); 422 | switch(paramIdx) { 423 | // Volume Envelope: 424 | case mB: 425 | voiceManager.updateInharmonicityCoeff(param->Value()); 426 | break; 427 | case mNumPartials: 428 | voiceManager.updateNumPartials(param->Value()); 429 | break; 430 | case mStringDetuneRange: 431 | voiceManager.updateStringDetuneRange(param->Value()); 432 | break; 433 | case mPartialDetuneRange: 434 | voiceManager.updatePartialDetuneRange(param->Value()); 435 | break; 436 | case mDamping: 437 | voiceManager.updateDamping(param->Value()); 438 | break; 439 | case mLinearTerm: 440 | voiceManager.updateLinearTerm(param->Value()); 441 | break; 442 | case mSquaredTerm: 443 | voiceManager.updateSquaredTerm(param->Value()); 444 | break; 445 | case mCubicTerm: 446 | voiceManager.updateCubicTerm(param->Value()); 447 | break; 448 | case mBrightnessA: 449 | voiceManager.updateBrightnessA(param->Value()); 450 | break; 451 | case mBrightnessB: 452 | voiceManager.updateBrightnessB(param->Value()); 453 | break; 454 | case mPitchBendCoarse: 455 | voiceManager.updatePitchBendCoarse(param->Value()); 456 | break; 457 | case mPitchBendFine: 458 | voiceManager.updatePitchBendFine(param->Value()); 459 | break; 460 | default: 461 | break; 462 | } 463 | } 464 | 465 | // This function will be called whenever the application receives a MIDI message. We're passing the messages through to our MIDI receiver. 466 | void Synthesis::ProcessMidiMsg(IMidiMsg* pMsg) { 467 | mMIDIReceiver.onMessageReceived(pMsg); 468 | mVirtualKeyboard->SetDirty(); 469 | } 470 | 471 | void Synthesis::processVirtualKeyboard() { 472 | IKeyboardControl* virtualKeyboard = (IKeyboardControl*) mVirtualKeyboard; 473 | int virtualKeyboardNoteNumber = virtualKeyboard->GetKey() + virtualKeyboardMinimumNoteNumber; 474 | 475 | if(lastVirtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) { 476 | // The note number has changed from a valid key to something else (valid key or nothing). Release the valid key: 477 | IMidiMsg midiMessage; 478 | midiMessage.MakeNoteOffMsg(lastVirtualKeyboardNoteNumber, 0); 479 | mMIDIReceiver.onMessageReceived(&midiMessage); 480 | } 481 | 482 | if (virtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) { 483 | // A valid key is pressed that wasn't pressed the previous call. Send a "note on" message to the MIDI receiver: 484 | IMidiMsg midiMessage; 485 | midiMessage.MakeNoteOnMsg(virtualKeyboardNoteNumber, virtualKeyboard->GetVelocity(), 0); 486 | mMIDIReceiver.onMessageReceived(&midiMessage); 487 | } 488 | 489 | lastVirtualKeyboardNoteNumber = virtualKeyboardNoteNumber; 490 | } 491 | 492 | void Synthesis::CreatePresets() { 493 | } -------------------------------------------------------------------------------- /Synthesis.exp: -------------------------------------------------------------------------------- 1 | _Synthesis_Entry 2 | _Synthesis_ViewEntry 3 | , -------------------------------------------------------------------------------- /Synthesis.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYNTHESIS__ 2 | #define __SYNTHESIS__ 3 | 4 | #pragma clang diagnostic push 5 | #pragma clang diagnostic ignored "-Wextra-tokens" 6 | #include "IPlug_include_in_plug_hdr.h" 7 | #pragma clang diagnostic pop 8 | #include "MIDIReceiver.h" 9 | #include "Oscilloscope.h" 10 | #include "VoiceManager.h" 11 | #include "Filter.h" 12 | #include 13 | #include 14 | 15 | class Synthesis : public IPlug 16 | { 17 | public: 18 | 19 | Synthesis(IPlugInstanceInfo instanceInfo); 20 | ~Synthesis(); 21 | 22 | void Reset(); 23 | void OnParamChange(int paramIdx); 24 | void ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames); 25 | void ProcessMidiMsg(IMidiMsg* pMsg); // to receive MIDI messages 26 | 27 | inline int GetNumKeys() const { return mMIDIReceiver.getNumKeys(); }; // Needed for the GUI keyboard - should return non-zero if one or more keys are playing. 28 | inline bool GetKeyStatus(int key) const { return mMIDIReceiver.getKeyStatus(key); }; // Should return true if the specified key is playing 29 | static const int virtualKeyboardMinimumNoteNumber = 24; 30 | int lastVirtualKeyboardNoteNumber; 31 | boost::array nextSample; 32 | 33 | private: 34 | 35 | void CreateParams(); 36 | void CreateGraphics(); 37 | void CreatePresets(); 38 | void InitOpenCL(); 39 | MIDIReceiver mMIDIReceiver; 40 | IControl* mVirtualKeyboard; 41 | void processVirtualKeyboard(); 42 | double clip(double sample); 43 | // Oscilloscope* mOscilloscope; 44 | OpenCL mOpenCL; 45 | Filter mFilterL; 46 | Filter mFilterR; 47 | boost::array blockOfSamples; 48 | 49 | void voiceEnergyUpdaterManager(); 50 | 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /Synthesis.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Synthesis 8 | SA_API;__WINDOWS_DS__;__WINDOWS_MM__;__WINDOWS_ASIO__; 9 | VST_API;VST_FORCE_DEPRECATED; 10 | VST3_API 11 | _DEBUG; 12 | NDEBUG; 13 | TRACER_BUILD;NDEBUG; 14 | $(ProjectDir)\..\..\..\MyDSP\; 15 | ..\..\ASIO_SDK;..\..\WDL\rtaudiomidi; 16 | dsound.lib;winmm.lib;Comctl32.lib; 17 | ..\..\VST3_SDK; 18 | .\..\..\AAX_SDK\Interfaces;.\..\..\AAX_SDK\Interfaces\ACF;.\..\..\AAX_SDK\Interfaces\C99Compatibility;.\..\..\WDL\IPlug\AAX 19 | AAX_API;_WINDOWS;WIN32;_WIN32;WINDOWS_VERSION;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE 20 | lice.lib;wininet.lib;odbc32.lib;odbccp32.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib 21 | .\..\..\WDL\IPlug\RTAS;.\ 22 | RTAS_API;_HAS_ITERATOR_DEBUGGING=0;_SECURE_SCL=0;_WINDOWS;WIN32;_WIN32;WINDOWS_VERSION;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE 23 | comdlg32.lib;uuid.lib;msimg32.lib;odbc32.lib;odbccp32.lib;user32.lib;gdi32.lib;advapi32.lib;shell32.lib 24 | 25 | 26 | $(BINARY_NAME) 27 | <_ProjectFileVersion>10.0.30319.1 28 | 29 | 30 | 31 | $(ADDITIONAL_INCLUDES);..\..\WDL;..\..\WDL\lice;..\..\WDL\IPlug 32 | 33 | 34 | IPlug.lib;lice.lib;%(AdditionalDependencies) 35 | 36 | 37 | 38 | 39 | $(BINARY_NAME) 40 | 41 | 42 | $(APP_DEFS) 43 | 44 | 45 | $(VST_DEFS) 46 | 47 | 48 | $(VST3_DEFS) 49 | 50 | 51 | $(DEBUG_DEFS) 52 | 53 | 54 | $(RELEASE_DEFS) 55 | 56 | 57 | $(TRACER_DEFS) 58 | 59 | 60 | $(ADDITIONAL_INCLUDES) 61 | 62 | 63 | $(APP_INCLUDES) 64 | 65 | 66 | $(APP_LIBS) 67 | 68 | 69 | $(VST3_INCLUDES) 70 | 71 | 72 | $(AAX_INCLUDES) 73 | 74 | 75 | $(AAX_DEFS) 76 | 77 | 78 | $(AAX_LIBS) 79 | 80 | 81 | $(RTAS_INCLUDES) 82 | 83 | 84 | $(RTAS_DEFS) 85 | 86 | 87 | $(RTAS_LIBS) 88 | 89 | 90 | -------------------------------------------------------------------------------- /Synthesis.rc: -------------------------------------------------------------------------------- 1 | #include "resource.h" 2 | 3 | KNOB_ID PNG KNOB_FN 4 | 5 | #ifdef SA_API 6 | //Standalone stuff 7 | #include 8 | 9 | IDI_ICON1 ICON DISCARDABLE "resources\Synthesis.ico" 10 | 11 | IDD_DIALOG_MAIN DIALOG DISCARDABLE 0, 0, GUI_WIDTH, GUI_HEIGHT 12 | STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX 13 | CAPTION "Synthesis" 14 | MENU IDR_MENU1 15 | FONT 8, "MS Sans Serif" 16 | BEGIN 17 | // EDITTEXT IDC_EDIT1,59,50,145,14,ES_AUTOHSCROLL 18 | // LTEXT "Enter some text here:",IDC_STATIC,59,39,73,8 19 | END 20 | 21 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 22 | IDD_DIALOG_PREF DIALOG DISCARDABLE 0, 0, 223, 309 23 | STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU 24 | CAPTION "Preferences" 25 | FONT 8, "MS Sans Serif" 26 | { 27 | DEFPUSHBUTTON "OK", IDOK, 110, 285, 50, 14 28 | PUSHBUTTON "Apply", IDAPPLY, 54, 285, 50, 14 29 | PUSHBUTTON "Cancel", IDCANCEL, 166, 285, 50, 14 30 | COMBOBOX IDC_COMBO_AUDIO_DRIVER, 20, 35, 100, 100, CBS_DROPDOWNLIST | CBS_HASSTRINGS 31 | LTEXT "Driver Type", IDC_STATIC, 22, 25, 38, 8, SS_LEFT 32 | COMBOBOX IDC_COMBO_AUDIO_IN_DEV, 20, 65, 100, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 33 | LTEXT "Input Device", IDC_STATIC, 20, 55, 42, 8, SS_LEFT 34 | COMBOBOX IDC_COMBO_AUDIO_OUT_DEV, 20, 95, 100, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 35 | LTEXT "Output Device", IDC_STATIC, 20, 85, 47, 8, SS_LEFT 36 | COMBOBOX IDC_COMBO_AUDIO_IOVS, 135, 35, 65, 100, CBS_DROPDOWNLIST | CBS_HASSTRINGS 37 | LTEXT "IO Vector Size", IDC_STATIC, 137, 25, 46, 8, SS_LEFT 38 | COMBOBOX IDC_COMBO_AUDIO_SIGVS, 135, 65, 65, 100, CBS_DROPDOWNLIST | CBS_HASSTRINGS 39 | LTEXT "Signal Vector Size", IDC_STATIC, 135, 55, 58, 8, SS_LEFT 40 | COMBOBOX IDC_COMBO_AUDIO_SR, 135, 95, 65, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 41 | LTEXT "Sampling Rate", IDC_STATIC, 135, 85, 47, 8, SS_LEFT 42 | GROUPBOX "Audio Device Settings", IDC_STATIC, 5, 10, 210, 170 43 | PUSHBUTTON "ASIO Config...", IDC_BUTTON_ASIO, 135, 155, 65, 14 44 | COMBOBOX IDC_COMBO_AUDIO_IN_L, 20, 125, 40, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 45 | LTEXT "Input 1 (L)", IDC_STATIC, 20, 115, 33, 8, SS_LEFT 46 | COMBOBOX IDC_COMBO_AUDIO_IN_R, 65, 126, 40, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 47 | LTEXT "Input 2 (R)", IDC_STATIC, 65, 115, 34, 8, SS_LEFT 48 | COMBOBOX IDC_COMBO_AUDIO_OUT_L, 20, 155, 40, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 49 | LTEXT "Output 1 (L)", IDC_STATIC, 20, 145, 38, 8, SS_LEFT 50 | COMBOBOX IDC_COMBO_AUDIO_OUT_R, 65, 155, 40, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 51 | LTEXT "Output 2 (R)", IDC_STATIC, 65, 145, 40, 8, SS_LEFT 52 | GROUPBOX "MIDI Device Settings", IDC_STATIC, 5, 190, 210, 85 53 | COMBOBOX IDC_COMBO_MIDI_OUT_DEV, 15, 250, 100, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 54 | LTEXT "Output Device", IDC_STATIC, 15, 240, 47, 8, SS_LEFT 55 | COMBOBOX IDC_COMBO_MIDI_IN_DEV, 15, 220, 100, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 56 | LTEXT "Input Device", IDC_STATIC, 15, 210, 42, 8, SS_LEFT 57 | LTEXT "Input Channel", IDC_STATIC, 125, 210, 45, 8, SS_LEFT 58 | COMBOBOX IDC_COMBO_MIDI_IN_CHAN, 125, 220, 50, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 59 | LTEXT "Output Channel", IDC_STATIC, 125, 240, 50, 8, SS_LEFT 60 | COMBOBOX IDC_COMBO_MIDI_OUT_CHAN, 125, 250, 50, 200, CBS_DROPDOWNLIST | CBS_HASSTRINGS 61 | AUTOCHECKBOX "Mono Input", IDC_CB_MONO_INPUT, 135, 127, 56, 8 62 | } 63 | 64 | IDR_MENU1 MENU DISCARDABLE 65 | BEGIN 66 | POPUP "&File" 67 | BEGIN 68 | // MENUITEM SEPARATOR 69 | MENUITEM "Preferences...", ID_PREFERENCES 70 | MENUITEM "&Quit", ID_QUIT 71 | END 72 | POPUP "&Help" 73 | BEGIN 74 | MENUITEM "&About", ID_ABOUT 75 | END 76 | END 77 | 78 | #endif // SA_API 79 | -------------------------------------------------------------------------------- /Synthesis.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Synthesis-app", "Synthesis-app.vcxproj", "{41785AE4-5B70-4A75-880B-4B418B4E13C6}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {3059A12C-2A45-439B-81EC-201D8ED347A3} = {3059A12C-2A45-439B-81EC-201D8ED347A3} 7 | {33958832-2FFD-49D8-9C13-5F0B26739E81} = {33958832-2FFD-49D8-9C13-5F0B26739E81} 8 | EndProjectSection 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IPlug", "..\..\WDL\IPlug\IPlug.vcxproj", "{33958832-2FFD-49D8-9C13-5F0B26739E81}" 11 | ProjectSection(ProjectDependencies) = postProject 12 | {3059A12C-2A45-439B-81EC-201D8ED347A3} = {3059A12C-2A45-439B-81EC-201D8ED347A3} 13 | EndProjectSection 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lice", "..\..\WDL\lice\lice.vcxproj", "{3059A12C-2A45-439B-81EC-201D8ED347A3}" 16 | EndProject 17 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Synthesis-vst2", "Synthesis-vst2.vcxproj", "{2EB4846A-93E0-43A0-821E-12237105168F}" 18 | ProjectSection(ProjectDependencies) = postProject 19 | {3059A12C-2A45-439B-81EC-201D8ED347A3} = {3059A12C-2A45-439B-81EC-201D8ED347A3} 20 | {33958832-2FFD-49D8-9C13-5F0B26739E81} = {33958832-2FFD-49D8-9C13-5F0B26739E81} 21 | EndProjectSection 22 | EndProject 23 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Synthesis-vst3", "Synthesis-vst3.vcxproj", "{079FC65A-F0E5-4E97-B318-A16D1D0B89DF}" 24 | ProjectSection(ProjectDependencies) = postProject 25 | {3059A12C-2A45-439B-81EC-201D8ED347A3} = {3059A12C-2A45-439B-81EC-201D8ED347A3} 26 | {33958832-2FFD-49D8-9C13-5F0B26739E81} = {33958832-2FFD-49D8-9C13-5F0B26739E81} 27 | {5755CC40-C699-491B-BD7C-5D841C26C28D} = {5755CC40-C699-491B-BD7C-5D841C26C28D} 28 | EndProjectSection 29 | EndProject 30 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "..\..\VST3_SDK\base\win\base_vc10.vcxproj", "{5755CC40-C699-491B-BD7C-5D841C26C28D}" 31 | EndProject 32 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Synthesis-aax", "Synthesis-aax.vcxproj", "{DC4B5920-933D-4C82-B842-F34431D55A93}" 33 | ProjectSection(ProjectDependencies) = postProject 34 | {3059A12C-2A45-439B-81EC-201D8ED347A3} = {3059A12C-2A45-439B-81EC-201D8ED347A3} 35 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53} = {5E3D286E-BF0D-446A-AFEF-E800F283CE53} 36 | EndProjectSection 37 | EndProject 38 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AAXLibrary", "..\..\AAX_SDK\Libs\AAXLibrary\WinBuild\AAXLibrary.vcxproj", "{5E3D286E-BF0D-446A-AFEF-E800F283CE53}" 39 | EndProject 40 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Synthesis-rtas", "Synthesis-rtas.vcxproj", "{8F427C1E-B580-4793-BEAC-F2CFEFA003F5}" 41 | ProjectSection(ProjectDependencies) = postProject 42 | {3059A12C-2A45-439B-81EC-201D8ED347A3} = {3059A12C-2A45-439B-81EC-201D8ED347A3} 43 | {D2CE28FF-63B8-48BC-936D-33F365B4053F} = {D2CE28FF-63B8-48BC-936D-33F365B4053F} 44 | EndProjectSection 45 | EndProject 46 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PlugInLib", "..\..\PT9_SDK\AlturaPorts\TDMPlugIns\PlugInLibrary\WinBuild\PlugInLib.vcxproj", "{D2CE28FF-63B8-48BC-936D-33F365B4053F}" 47 | EndProject 48 | Global 49 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 50 | Debug|Win32 = Debug|Win32 51 | Debug|x64 = Debug|x64 52 | Release|Win32 = Release|Win32 53 | Release|x64 = Release|x64 54 | Tracer|Win32 = Tracer|Win32 55 | Tracer|x64 = Tracer|x64 56 | EndGlobalSection 57 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 58 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Debug|Win32.ActiveCfg = Debug|Win32 59 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Debug|Win32.Build.0 = Debug|Win32 60 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Debug|x64.ActiveCfg = Debug|x64 61 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Debug|x64.Build.0 = Debug|x64 62 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Release|Win32.ActiveCfg = Release|Win32 63 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Release|Win32.Build.0 = Release|Win32 64 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Release|x64.ActiveCfg = Release|x64 65 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Release|x64.Build.0 = Release|x64 66 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Tracer|Win32.ActiveCfg = Tracer|Win32 67 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Tracer|Win32.Build.0 = Tracer|Win32 68 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Tracer|x64.ActiveCfg = Tracer|x64 69 | {41785AE4-5B70-4A75-880B-4B418B4E13C6}.Tracer|x64.Build.0 = Tracer|x64 70 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Debug|Win32.ActiveCfg = Debug|Win32 71 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Debug|Win32.Build.0 = Debug|Win32 72 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Debug|x64.ActiveCfg = Debug|x64 73 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Debug|x64.Build.0 = Debug|x64 74 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Release|Win32.ActiveCfg = Release|Win32 75 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Release|Win32.Build.0 = Release|Win32 76 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Release|x64.ActiveCfg = Release|x64 77 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Release|x64.Build.0 = Release|x64 78 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Tracer|Win32.ActiveCfg = Tracer|Win32 79 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Tracer|Win32.Build.0 = Tracer|Win32 80 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Tracer|x64.ActiveCfg = Tracer|x64 81 | {33958832-2FFD-49D8-9C13-5F0B26739E81}.Tracer|x64.Build.0 = Tracer|x64 82 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Debug|Win32.ActiveCfg = Debug|Win32 83 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Debug|Win32.Build.0 = Debug|Win32 84 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Debug|x64.ActiveCfg = Debug|x64 85 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Debug|x64.Build.0 = Debug|x64 86 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Release|Win32.ActiveCfg = Release|Win32 87 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Release|Win32.Build.0 = Release|Win32 88 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Release|x64.ActiveCfg = Release|x64 89 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Release|x64.Build.0 = Release|x64 90 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Tracer|Win32.ActiveCfg = Release|Win32 91 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Tracer|Win32.Build.0 = Release|Win32 92 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Tracer|x64.ActiveCfg = Release|x64 93 | {3059A12C-2A45-439B-81EC-201D8ED347A3}.Tracer|x64.Build.0 = Release|x64 94 | {2EB4846A-93E0-43A0-821E-12237105168F}.Debug|Win32.ActiveCfg = Debug|Win32 95 | {2EB4846A-93E0-43A0-821E-12237105168F}.Debug|Win32.Build.0 = Debug|Win32 96 | {2EB4846A-93E0-43A0-821E-12237105168F}.Debug|x64.ActiveCfg = Debug|x64 97 | {2EB4846A-93E0-43A0-821E-12237105168F}.Debug|x64.Build.0 = Debug|x64 98 | {2EB4846A-93E0-43A0-821E-12237105168F}.Release|Win32.ActiveCfg = Release|Win32 99 | {2EB4846A-93E0-43A0-821E-12237105168F}.Release|Win32.Build.0 = Release|Win32 100 | {2EB4846A-93E0-43A0-821E-12237105168F}.Release|x64.ActiveCfg = Release|x64 101 | {2EB4846A-93E0-43A0-821E-12237105168F}.Release|x64.Build.0 = Release|x64 102 | {2EB4846A-93E0-43A0-821E-12237105168F}.Tracer|Win32.ActiveCfg = Tracer|Win32 103 | {2EB4846A-93E0-43A0-821E-12237105168F}.Tracer|Win32.Build.0 = Tracer|Win32 104 | {2EB4846A-93E0-43A0-821E-12237105168F}.Tracer|x64.ActiveCfg = Tracer|x64 105 | {2EB4846A-93E0-43A0-821E-12237105168F}.Tracer|x64.Build.0 = Tracer|x64 106 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Debug|Win32.ActiveCfg = Debug|Win32 107 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Debug|Win32.Build.0 = Debug|Win32 108 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Debug|x64.ActiveCfg = Debug|x64 109 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Debug|x64.Build.0 = Debug|x64 110 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Release|Win32.ActiveCfg = Release|Win32 111 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Release|Win32.Build.0 = Release|Win32 112 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Release|x64.ActiveCfg = Release|x64 113 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Release|x64.Build.0 = Release|x64 114 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Tracer|Win32.ActiveCfg = Tracer|Win32 115 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Tracer|Win32.Build.0 = Tracer|Win32 116 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Tracer|x64.ActiveCfg = Tracer|x64 117 | {079FC65A-F0E5-4E97-B318-A16D1D0B89DF}.Tracer|x64.Build.0 = Tracer|x64 118 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Debug|Win32.ActiveCfg = Debug|Win32 119 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Debug|Win32.Build.0 = Debug|Win32 120 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Debug|x64.ActiveCfg = Debug|x64 121 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Debug|x64.Build.0 = Debug|x64 122 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Release|Win32.ActiveCfg = Release|Win32 123 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Release|Win32.Build.0 = Release|Win32 124 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Release|x64.ActiveCfg = Release|x64 125 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Release|x64.Build.0 = Release|x64 126 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Tracer|Win32.ActiveCfg = Release|Win32 127 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Tracer|Win32.Build.0 = Release|Win32 128 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Tracer|x64.ActiveCfg = Release|x64 129 | {5755CC40-C699-491B-BD7C-5D841C26C28D}.Tracer|x64.Build.0 = Release|x64 130 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Debug|Win32.ActiveCfg = Debug|Win32 131 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Debug|Win32.Build.0 = Debug|Win32 132 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Debug|x64.ActiveCfg = Debug|x64 133 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Debug|x64.Build.0 = Debug|x64 134 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Release|Win32.ActiveCfg = Release|Win32 135 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Release|Win32.Build.0 = Release|Win32 136 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Release|x64.ActiveCfg = Release|x64 137 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Release|x64.Build.0 = Release|x64 138 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Tracer|Win32.ActiveCfg = Tracer|Win32 139 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Tracer|Win32.Build.0 = Tracer|Win32 140 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Tracer|x64.ActiveCfg = Tracer|x64 141 | {DC4B5920-933D-4C82-B842-F34431D55A93}.Tracer|x64.Build.0 = Tracer|x64 142 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Debug|Win32.ActiveCfg = Debug|Win32 143 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Debug|Win32.Build.0 = Debug|Win32 144 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Debug|x64.ActiveCfg = Debug|x64 145 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Debug|x64.Build.0 = Debug|x64 146 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Release|Win32.ActiveCfg = Release|Win32 147 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Release|Win32.Build.0 = Release|Win32 148 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Release|x64.ActiveCfg = Release|x64 149 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Release|x64.Build.0 = Release|x64 150 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Tracer|Win32.ActiveCfg = Release|Win32 151 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Tracer|Win32.Build.0 = Release|Win32 152 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Tracer|x64.ActiveCfg = Release|x64 153 | {5E3D286E-BF0D-446A-AFEF-E800F283CE53}.Tracer|x64.Build.0 = Release|x64 154 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Debug|Win32.ActiveCfg = Debug|Win32 155 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Debug|Win32.Build.0 = Debug|Win32 156 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Debug|x64.ActiveCfg = Debug|Win32 157 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Release|Win32.ActiveCfg = Release|Win32 158 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Release|Win32.Build.0 = Release|Win32 159 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Release|x64.ActiveCfg = Release|Win32 160 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Tracer|Win32.ActiveCfg = Tracer|Win32 161 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Tracer|Win32.Build.0 = Tracer|Win32 162 | {8F427C1E-B580-4793-BEAC-F2CFEFA003F5}.Tracer|x64.ActiveCfg = Tracer|Win32 163 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Debug|Win32.ActiveCfg = Release|Win32 164 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Debug|Win32.Build.0 = Release|Win32 165 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Debug|x64.ActiveCfg = Debug|Win32 166 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Release|Win32.ActiveCfg = Release|Win32 167 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Release|Win32.Build.0 = Release|Win32 168 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Release|x64.ActiveCfg = Release|Win32 169 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Tracer|Win32.ActiveCfg = Release|Win32 170 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Tracer|Win32.Build.0 = Release|Win32 171 | {D2CE28FF-63B8-48BC-936D-33F365B4053F}.Tracer|x64.ActiveCfg = Release|Win32 172 | EndGlobalSection 173 | GlobalSection(SolutionProperties) = preSolution 174 | HideSolutionNode = FALSE 175 | EndGlobalSection 176 | EndGlobal 177 | -------------------------------------------------------------------------------- /Voice.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Voice.cpp 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/21/14. 6 | // 7 | // 8 | 9 | #include "Voice.h" 10 | 11 | void Voice::setFree() { 12 | isActive = false; 13 | reset(); 14 | } 15 | 16 | void Voice::reset() { 17 | mNoteNumber = -1; 18 | mVelocity = 0.0f; 19 | mTime = 0.0f; 20 | //mOscillator.reset(); 21 | } -------------------------------------------------------------------------------- /Voice.h: -------------------------------------------------------------------------------- 1 | // 2 | // Voice.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/21/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__Voice__ 10 | #define __Synthesis__Voice__ 11 | 12 | #include 13 | #include "Oscillator.h" 14 | #include 15 | 16 | class Voice { 17 | 18 | public: 19 | friend class VoiceManager; 20 | // constructor: 21 | Voice() 22 | : mNoteNumber(-1), 23 | mVelocity(0.0f), 24 | mEnergyVert(0.0f), 25 | mEnergyHoriz(0.0f), 26 | mHorizToVertRatio(0.3f), 27 | mDamping(0.0f), 28 | mBrownianThreshold(0.00001), 29 | lastExcitationTimeAgo(0.0f), 30 | lastExcitationDuration(0.0f), 31 | lastExcitationStrength(0.0f), 32 | isActive(false) {} 33 | // public member functions: 34 | inline void setNoteNumber(int noteNumber) { 35 | mNoteNumber = noteNumber; 36 | mFrequency = 440.0f * powf(2.0f, (mNoteNumber - 69.0f) / 12.0f); 37 | mOscillator.setFrequency(mFrequency); 38 | } 39 | void setFree(); 40 | void reset(); 41 | 42 | private: 43 | Oscillator mOscillator; 44 | int mNoteNumber; 45 | float mTime; /// time counter for this voice, since last voice reset() 46 | float mEnergyVert; // energy stored in the vertical mode of vibration for this voice (decays faster) 47 | float mEnergyHoriz; // energy stored in the horizontal mode of vibration for this voice (decays slower) 48 | float mHorizToVertRatio; /// I could generalize this later to be, instead of vert and horiz, do an arbitrary number of axes of vibrations that create an N-stage amplitude decay! // range (0, 1), dictates how much slower horiz energy decays compared to vert energy (based on differing admittances at the string bridge) --> 0.5 indicates they decay at the same rate, while 0.1 means vert decays 10 times faster 49 | float mDamping; // current damping value for this voice 50 | float mBrownianThreshold; // minimum mEnergy value below which we'll reset the voice 51 | float mFrequency; 52 | float mVelocity; 53 | float mStringDetuneAmount; 54 | float randomSeed; // stored as float b/c passing in as float to kernel 55 | float lastExcitationTimeAgo; // how many samples ago the last excitation occurred for this voice 56 | float lastExcitationDuration; // in samples /// WARNING: this may cause an error on sample rate switch... or just audible artifacts... maybe ok 57 | float lastExcitationStrength; 58 | bool isActive; 59 | }; 60 | 61 | #endif /* defined(__Synthesis__Voice__) */ 62 | -------------------------------------------------------------------------------- /VoiceManager.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // VoiceManager.cpp 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/21/14. 6 | // 7 | // 8 | 9 | #include "VoiceManager.h" 10 | 11 | int VoiceManager::getNumberOfActiveVoices() { 12 | int count = 0; 13 | for (int i = 0; i < MAX_VOICES; i++) { 14 | if (voices[i].isActive) { 15 | count++; 16 | } 17 | } 18 | return count; 19 | } 20 | 21 | Voice* VoiceManager::findVoicePlayingSameNote(int noteNumber) { 22 | Voice* sameNoteVoice = NULL; 23 | for (int i = 0; i < MAX_VOICES; i++) { 24 | if (voices[i].mNoteNumber == noteNumber) { 25 | sameNoteVoice = &(voices[i]); 26 | break; 27 | } 28 | } 29 | return sameNoteVoice; 30 | } 31 | 32 | Voice* VoiceManager::findFreeVoice() { 33 | Voice* freeVoice = NULL; 34 | for (int i = 0; i < MAX_VOICES; i++) { 35 | if (!voices[i].isActive) { 36 | freeVoice = &(voices[i]); 37 | break; 38 | } 39 | } 40 | return freeVoice; 41 | } 42 | 43 | Voice* VoiceManager::findOldestVoice() { 44 | double age = 0.0; 45 | int indexOfOldest = 0; 46 | for (int i = 0; i < MAX_VOICES; i++) { 47 | if (voices[i].mTime > age) { 48 | age = voices[i].mTime; 49 | indexOfOldest = i; 50 | } 51 | } 52 | return &(voices[indexOfOldest]); 53 | } 54 | 55 | void VoiceManager::onNoteOn(int noteNumber, int velocity) { 56 | // print number of active voices 57 | //std::cout << "\nActive voices = " << getNumberOfActiveVoices(); 58 | // first look for a voice that's playing the same note 59 | // Voice* voice = findVoicePlayingSameNote(noteNumber); 60 | // // if no voice playing same note, look for a free voice 61 | // if (!voice) { 62 | // voice = findFreeVoice(); 63 | // } 64 | 65 | Voice* voice = findFreeVoice(); 66 | // then do voice stealing 67 | if (!voice) { 68 | voice = findOldestVoice(); 69 | //printf("stole a voice!"); 70 | } 71 | 72 | /// velocity scaling (scaling from int (0, 127) to float (0,1) WITH velocity curve) 73 | //float scaledVelocity = 0.14948f * powf(1.055f, 0.3f*velocity)-0.14948f; // velocity scaling to (0, 1) w/velocity curve 74 | 75 | float scaledVelocity = velocity / 127.0f; 76 | 77 | voice->reset(); 78 | voice->setNoteNumber(noteNumber); 79 | //voice->mDamping = ((float)noteNumber/100.0f)*2.5f; /// set this to be a param amount set by a knob (and modified by expression pedal) to control decay time 80 | voice->mDamping = ((float)noteNumber/100.0f)*mOpenCL.mDamping; 81 | voice->lastExcitationTimeAgo = 0.0f; 82 | voice->lastExcitationStrength = scaledVelocity; 83 | voice->lastExcitationDuration = 0.005f; // 5ms 84 | voice->isActive = true; 85 | voice->mVelocity = scaledVelocity; 86 | 87 | voice->mEnergyHoriz *= (1-scaledVelocity); // louder hits will "reset" the velocity more - a full loudness hit will totally reset the string back to zero energy 88 | voice->mEnergyVert *= (1-scaledVelocity); 89 | 90 | //voice->mEnergyHoriz = scaledVelocity; 91 | //voice->mEnergyVert = scaledVelocity; 92 | //printf("---NOTE ON---\n"); 93 | //voice->mEnergy = scaledVelocity; /// actually this should also be a RAMP function so we get a smooth ramping up to the target mEnergy value 94 | voice->mStringDetuneAmount = (1.0f-mOpenCL.mStringDetuneRange) + static_cast (rand()) /( static_cast (RAND_MAX/(2.0f*mOpenCL.mStringDetuneRange))); 95 | voice->randomSeed = rand() % 10000+1000; // set random seed on each note hit for randomizing partial frequencies and amplitudes 96 | } 97 | 98 | void VoiceManager::onNoteOff(int noteNumber, int velocity) { 99 | for (int i = 0; i < MAX_VOICES; i++) { 100 | Voice& voice = voices[i]; 101 | if (voice.isActive && voice.mNoteNumber == noteNumber) { 102 | //voice.mDamping = 50.0f; /// actually, this should be a RAMP function, which takes target mDamping value and # of samples it'll take to get there (or SPEED), and then the function increases damping gradually (iterates over several samples of the damping array, perhaps? how to handle this?) 103 | } 104 | } 105 | } 106 | 107 | void VoiceManager::onSustainChange(double sustain) { 108 | mOpenCL.MIDIParams[0] = (float)sustain; 109 | } 110 | 111 | void VoiceManager::onExpressionChange(double expression) { 112 | mOpenCL.MIDIParams[1] = (float)expression; 113 | } 114 | 115 | void VoiceManager::onModChange(double mod) { 116 | // mOpenCL.MIDIParams[2] = (float)mod; 117 | mOpenCL.mModCurrent = (float)mod; 118 | } 119 | 120 | void VoiceManager::setSampleRate(double sampleRate) { 121 | } 122 | 123 | void VoiceManager::updateVoiceData() { 124 | int j = 0; 125 | for (int i = 0; i < MAX_VOICES; i++) { 126 | Voice& voice = voices[i]; 127 | if (voice.isActive) { 128 | mOpenCL.voicesData[j*NUM_VOICE_PARAMS] = voice.mTime; 129 | mOpenCL.voicesData[j*NUM_VOICE_PARAMS+1] = voice.mFrequency; 130 | mOpenCL.voicesData[j*NUM_VOICE_PARAMS+2] = voice.mVelocity; 131 | mOpenCL.voicesData[j*NUM_VOICE_PARAMS+3] = voice.mStringDetuneAmount; 132 | mOpenCL.voicesData[j*NUM_VOICE_PARAMS+4] = voice.randomSeed; 133 | j++; 134 | voice.mTime += mOpenCL.mTimeStep * BLOCK_SIZE; 135 | } 136 | } 137 | } 138 | 139 | void VoiceManager::setFreeInaudibleVoices() { 140 | for (int i = 0; i < MAX_VOICES; i++) { 141 | Voice& voice = voices[i]; 142 | if (voice.isActive) { 143 | if ((voice.mEnergyHoriz + voice.mEnergyVert) <= voice.mBrownianThreshold) { 144 | voice.setFree(); 145 | // printf("voice %d set free!\n", i); 146 | } 147 | } 148 | } 149 | } 150 | 151 | void VoiceManager::updateVoiceDampingAndEnergy(int currentSampleIndex) { 152 | int j = 0; 153 | for (int i = 0; i < MAX_VOICES; i++) { 154 | Voice& voice = voices[i]; 155 | if (voice.isActive) { 156 | float duration = voice.lastExcitationDuration; 157 | float timeAgo = voice.lastExcitationTimeAgo; 158 | float timeStep = mOpenCL.mTimeStep; 159 | if (timeAgo < duration) { 160 | float deltaEnergy = timeStep * static_cast( exp( - ( pow(timeAgo - duration/2.0f, 2) / (duration*duration*0.03f) ) ) ) * voice.lastExcitationStrength * 500.0f; // smooth ramp for energy // gaussian distribution force function that starts increasing immediately after strike and goes back down to zero after exactly duration seconds. the 0.03f is so that the gaussian curve just touches zero at the beginning and end of the transient 161 | voice.mEnergyVert += deltaEnergy * (1.0f-voice.mHorizToVertRatio); // this was just 1.0, with 250.0f final multiplier in above line 162 | voice.mEnergyHoriz += deltaEnergy * voice.mHorizToVertRatio; 163 | //printf("timeAgo = %f, duration = %f, voice[%d] energyVert = %f, energyHoriz = %f\n", timeAgo, duration, i, voice.mEnergyVert, voice.mEnergyHoriz); 164 | } 165 | if (currentSampleIndex == 0) { 166 | //printf("timeAgo = %f, duration = %f, voice[%d] energyVert = %f, energyHoriz = %f\n", timeAgo, duration, i, voice.mEnergyVert, voice.mEnergyHoriz); 167 | } 168 | voice.mEnergyVert -= voice.mEnergyVert * timeStep * voice.mDamping * (1.0f-voice.mHorizToVertRatio); 169 | voice.mEnergyHoriz -= voice.mEnergyHoriz * timeStep * voice.mDamping * (voice.mHorizToVertRatio); 170 | mOpenCL.voicesEnergy[j*BLOCK_SIZE + currentSampleIndex] = voice.mEnergyVert + voice.mEnergyHoriz; // set voice energy with sum of horizontal and vertical modes of string vibration 171 | voice.lastExcitationTimeAgo += mOpenCL.mTimeStep; 172 | j++; 173 | } 174 | } 175 | } 176 | 177 | boost::array VoiceManager::getBlockOfSamples() { 178 | 179 | numActiveVoices = getNumberOfActiveVoices(); 180 | mOpenCL.NUM_ACTIVE_VOICES = numActiveVoices; 181 | //std::cout << "\nactive voices: " << numActiveVoices; 182 | if (numActiveVoices == 0) { 183 | return zeroes; 184 | } else { 185 | updateVoiceData(); // writes new voice data to mOpenCL 186 | return mOpenCL.getBlockOfSamples(); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /VoiceManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VoiceManager.h 3 | // Synthesis 4 | // 5 | // Created by Devin Mooers on 1/21/14. 6 | // 7 | // 8 | 9 | #ifndef __Synthesis__VoiceManager__ 10 | #define __Synthesis__VoiceManager__ 11 | 12 | #include 13 | #include "Voice.h" 14 | #include 15 | #include "OpenCL.h" 16 | 17 | class VoiceManager { 18 | public: 19 | static VoiceManager& getInstance() { 20 | static VoiceManager theInstance; 21 | return theInstance; 22 | }; 23 | void onNoteOn(int noteNumber, int velocity); 24 | void onNoteOff(int noteNumber, int velocity); 25 | void onSustainChange(double sustain); 26 | void onExpressionChange(double expression); 27 | void onModChange(double mod); 28 | void setSampleRate(double sampleRate); 29 | void updateInharmonicityCoeff(float mB) { 30 | mOpenCL.mB = mB; 31 | } 32 | void updateNumPartials(int partials) { 33 | mOpenCL.NUM_PARTIALS = partials; 34 | } 35 | void updateStringDetuneRange(float val) { 36 | mOpenCL.mStringDetuneRange = val; 37 | } 38 | void updatePartialDetuneRange(float val) { 39 | mOpenCL.mPartialDetuneRange = val; 40 | } 41 | void updateDamping(float val) { 42 | mOpenCL.mDamping = val; 43 | } 44 | void updateLinearTerm(float val) { 45 | mOpenCL.instrumentData[0] = val; 46 | } 47 | void updateSquaredTerm(float val) { 48 | mOpenCL.instrumentData[1] = val; 49 | } 50 | void updateCubicTerm(float val) { 51 | mOpenCL.instrumentData[2] = val; 52 | } 53 | void updateBrightnessA(float val) { 54 | mOpenCL.instrumentData[3] = val; 55 | } 56 | void updateBrightnessB(float val) { 57 | mOpenCL.instrumentData[4] = val; 58 | } 59 | void updatePitchBendCoarse(float val) { 60 | mOpenCL.instrumentData[5] = val; 61 | } 62 | void updatePitchBendFine(float val) { 63 | mOpenCL.instrumentData[6] = val; 64 | } 65 | boost::array getBlockOfSamples(); 66 | inline void initOpenCL() { 67 | zeroes.assign(0.0); 68 | currentEnergySampleIndex = 0; 69 | mOpenCL.initOpenCL(); 70 | } 71 | void updateVoiceDampingAndEnergy(int i); 72 | void setFreeInaudibleVoices(); 73 | OpenCL mOpenCL; 74 | 75 | private: 76 | /* No instantiation from outside (i.e. singleton) */ 77 | VoiceManager() {}; 78 | /* Explicitly disallow copying: */ 79 | VoiceManager(const VoiceManager&); 80 | VoiceManager& operator= (const VoiceManager&); 81 | Voice voices[MAX_VOICES]; 82 | int getNumberOfActiveVoices(); 83 | int numActiveVoices; 84 | int currentEnergySampleIndex; 85 | void updateVoiceData(); // this is called on every sample to update damping and energy values 86 | Voice* findVoicePlayingSameNote(int noteNumber); 87 | Voice* findFreeVoice(); 88 | Voice* findOldestVoice(); 89 | boost::array zeroes; // zero-samples for returning if no active voices 90 | }; 91 | 92 | #endif /* defined(__Synthesis__VoiceManager__) */ 93 | -------------------------------------------------------------------------------- /app_wrapper/app_main.h: -------------------------------------------------------------------------------- 1 | #ifndef _IPLUGAPP_APP_MAIN_H_ 2 | #define _IPLUGAPP_APP_MAIN_H_ 3 | 4 | #include "IPlugOSDetect.h" 5 | 6 | /* 7 | 8 | Standalone osx/win app wrapper for iPlug, using SWELL 9 | Oli Larkin 2012 10 | 11 | Notes: 12 | 13 | App settings are stored in a .ini file. The location is as follows: 14 | 15 | Windows7: C:\Users\USERNAME\AppData\Local\Synthesis\settings.ini 16 | Windows XP/Vista: C:\Documents and Settings\USERNAME\Local Settings\Application Data\Synthesis\settings.ini 17 | OSX: /Users/USERNAME/Library/Application\ Support/Synthesis/settings.ini 18 | 19 | */ 20 | 21 | #ifdef OS_WIN 22 | #include 23 | #include 24 | 25 | #define DEFAULT_INPUT_DEV "Default Device" 26 | #define DEFAULT_OUTPUT_DEV "Default Device" 27 | 28 | #define DAC_DS 0 29 | #define DAC_ASIO 1 30 | #else if defined OS_OSX 31 | #include "swell.h" 32 | #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) 33 | 34 | #define DEFAULT_INPUT_DEV "Built-in Microphone" // changed from Built-in Output per Martin Finke's tutorial 35 | #define DEFAULT_OUTPUT_DEV "Built-in Output" 36 | 37 | #define DAC_COREAUDIO 0 38 | // #define DAC_JACK 1 39 | #endif 40 | 41 | #include "wdltypes.h" 42 | #include "RtAudio.h" 43 | #include "RtMidi.h" 44 | #include 45 | #include 46 | 47 | #include "../Synthesis.h" // change this to match your iplug plugin .h file 48 | 49 | typedef unsigned short UInt16; 50 | 51 | struct AppState 52 | { 53 | // on osx core audio 0 or jack 1 54 | // on windows DS 0 or ASIO 1 55 | UInt16 mAudioDriverType; 56 | 57 | // strings 58 | char mAudioInDev[100]; 59 | char mAudioOutDev[100]; 60 | char mAudioSR[100]; 61 | char mAudioIOVS[100]; 62 | char mAudioSigVS[100]; 63 | 64 | UInt16 mAudioInChanL; 65 | UInt16 mAudioInChanR; 66 | UInt16 mAudioOutChanL; 67 | UInt16 mAudioOutChanR; 68 | UInt16 mAudioInIsMono; 69 | 70 | // strings containing the names of the midi devices 71 | char mMidiInDev[100]; 72 | char mMidiOutDev[100]; 73 | 74 | UInt16 mMidiInChan; 75 | UInt16 mMidiOutChan; 76 | 77 | AppState(): 78 | mAudioDriverType(0), // DS / CoreAudio by default 79 | mAudioInChanL(1), 80 | mAudioInChanR(2), 81 | mAudioOutChanL(1), 82 | mAudioOutChanR(2), 83 | mMidiInChan(0), 84 | mMidiOutChan(0) 85 | { 86 | strcpy(mAudioInDev, DEFAULT_INPUT_DEV); 87 | strcpy(mAudioOutDev, DEFAULT_OUTPUT_DEV); 88 | strcpy(mAudioSR, "44100"); 89 | strcpy(mAudioIOVS, "512"); 90 | strcpy(mAudioSigVS, "32"); 91 | 92 | strcpy(mMidiInDev, "off"); 93 | strcpy(mMidiOutDev, "off"); 94 | } 95 | }; 96 | 97 | extern WDL_DLGRET MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 98 | extern WDL_DLGRET PreferencesDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 99 | extern HINSTANCE gHINST; 100 | extern HWND gHWND; 101 | extern UINT gScrollMessage; 102 | extern IPlug* gPluginInstance; // The iplug plugin instance 103 | 104 | extern std::string GetAudioDeviceName(int idx); 105 | extern int GetAudioDeviceID(char* deviceNameToTest); 106 | 107 | extern void ProbeAudioIO(); 108 | extern bool InitialiseAudio(unsigned int inId, 109 | unsigned int outId, 110 | unsigned int sr, 111 | unsigned int iovs, 112 | unsigned int chnls, 113 | unsigned int inChanL, 114 | unsigned int outChanL 115 | ); 116 | 117 | extern bool AudioSettingsInStateAreEqual(AppState* os, AppState* ns); 118 | extern bool MIDISettingsInStateAreEqual(AppState* os, AppState* ns); 119 | 120 | extern bool TryToChangeAudioDriverType(); 121 | extern bool TryToChangeAudio(); 122 | extern bool ChooseMidiInput(const char* pPortName); 123 | extern bool ChooseMidiOutput(const char* pPortName); 124 | 125 | extern bool AttachGUI(); 126 | 127 | extern RtAudio* gDAC; 128 | extern RtMidiIn *gMidiIn; 129 | extern RtMidiOut *gMidiOut; 130 | 131 | extern AppState *gState; 132 | extern AppState *gTempState; // The state is copied here when the pref dialog is opened, and restored if cancel is pressed 133 | extern AppState *gActiveState; // When the audio driver is started the current state is copied here so that if OK is pressed after APPLY nothing is changed 134 | 135 | extern unsigned int gSigVS; 136 | extern unsigned int gBufIndex; // index for signal vector, loops from 0 to gSigVS 137 | 138 | extern char *gINIPath; // path of ini file 139 | extern void UpdateINI(); 140 | 141 | extern std::vector gAudioInputDevs; 142 | extern std::vector gAudioOutputDevs; 143 | extern std::vector gMIDIInputDevNames; 144 | extern std::vector gMIDIOutputDevNames; 145 | 146 | #endif //_IPLUGAPP_APP_MAIN_H_ 147 | 148 | -------------------------------------------------------------------------------- /app_wrapper/app_resource.h: -------------------------------------------------------------------------------- 1 | // RESOURCE IDS FOR STANDALONE APP 2 | 3 | #ifndef IDC_STATIC 4 | #define IDC_STATIC (-1) 5 | #endif 6 | 7 | #define IDD_DIALOG_MAIN 40001 8 | #define IDD_DIALOG_PREF 40002 9 | #define IDI_ICON1 40003 10 | #define IDR_MENU1 40004 11 | 12 | #define ID_ABOUT 40005 13 | #define ID_PREFERENCES 40006 14 | #define ID_QUIT 40007 15 | 16 | #define IDC_COMBO_AUDIO_DRIVER 40008 17 | #define IDC_COMBO_AUDIO_IN_DEV 40009 18 | #define IDC_COMBO_AUDIO_OUT_DEV 40010 19 | #define IDC_COMBO_AUDIO_IOVS 40011 20 | #define IDC_COMBO_AUDIO_SIGVS 40012 21 | #define IDC_COMBO_AUDIO_SR 40013 22 | #define IDC_COMBO_AUDIO_IN_L 40014 23 | #define IDC_COMBO_AUDIO_IN_R 40015 24 | #define IDC_COMBO_AUDIO_OUT_R 40016 25 | #define IDC_COMBO_AUDIO_OUT_L 40017 26 | #define IDC_COMBO_MIDI_IN_DEV 40018 27 | #define IDC_COMBO_MIDI_OUT_DEV 40019 28 | #define IDC_COMBO_MIDI_IN_CHAN 40020 29 | #define IDC_COMBO_MIDI_OUT_CHAN 40021 30 | #define IDC_BUTTON_ASIO 40022 31 | #define IDC_CB_MONO_INPUT 40023 32 | 33 | #define IDAPPLY 40024 34 | 35 | // some options for the app 36 | 37 | #define ENABLE_SYSEX 0 38 | #define ENABLE_MIDICLOCK 0 39 | #define ENABLE_ACTIVE_SENSING 0 40 | #define NUM_CHANNELS 2 41 | #define N_VECTOR_WAIT 50 42 | #define APP_MULT 0.25 43 | -------------------------------------------------------------------------------- /app_wrapper/main.mm: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | return NSApplicationMain(argc, (const char **) argv); 6 | } 7 | -------------------------------------------------------------------------------- /installer/Synthesis-installer-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/installer/Synthesis-installer-bg.png -------------------------------------------------------------------------------- /installer/Synthesis.iss: -------------------------------------------------------------------------------- 1 | [Setup] 2 | AppName=Synthesis 3 | AppVersion=1.0.0 4 | DefaultDirName={pf}\Synthesis 5 | DefaultGroupName=Synthesis 6 | Compression=lzma2 7 | SolidCompression=yes 8 | OutputDir=.\ 9 | ArchitecturesInstallIn64BitMode=x64 10 | OutputBaseFilename=Synthesis Installer 11 | LicenseFile=license.rtf 12 | SetupLogging=yes 13 | 14 | [Types] 15 | Name: "full"; Description: "Full installation" 16 | Name: "custom"; Description: "Custom installation"; Flags: iscustom 17 | 18 | [Components] 19 | Name: "app"; Description: "Standalone application (.exe)"; Types: full custom; 20 | Name: "vst2_32"; Description: "32-bit VST2 Plugin (.dll)"; Types: full custom; 21 | Name: "vst2_64"; Description: "64-bit VST2 Plugin (.dll)"; Types: full custom; Check: Is64BitInstallMode; 22 | Name: "vst3_32"; Description: "32-bit VST3 Plugin (.vst3)"; Types: full custom; 23 | Name: "vst3_64"; Description: "64-bit VST3 Plugin (.vst3)"; Types: full custom; Check: Is64BitInstallMode; 24 | Name: "rtas_32"; Description: "32-bit RTAS Plugin (.dpm)"; Types: full custom; 25 | Name: "aax_32"; Description: "32-bit AAX Plugin (.aaxplugin)"; Types: full custom; 26 | Name: "manual"; Description: "User guide"; Types: full custom; Flags: fixed 27 | 28 | [Files] 29 | Source: "..\build-win\app\Win32\bin\Synthesis.exe"; DestDir: "{app}"; Check: not Is64BitInstallMode; Components:app; Flags: ignoreversion; 30 | Source: "..\build-win\app\x64\bin\Synthesis.exe"; DestDir: "{app}"; Check: Is64BitInstallMode; Components:app; Flags: ignoreversion; 31 | 32 | Source: "..\build-win\vst2\Win32\bin\Synthesis.dll"; DestDir: {code:GetVST2Dir_32}; Check: not Is64BitInstallMode; Components:vst2_32; Flags: ignoreversion; 33 | Source: "..\build-win\vst2\Win32\bin\Synthesis.dll"; DestDir: {code:GetVST2Dir_32}; Check: Is64BitInstallMode; Components:vst2_32; Flags: ignoreversion; 34 | Source: "..\build-win\vst2\x64\bin\Synthesis.dll"; DestDir: {code:GetVST2Dir_64}; Check: Is64BitInstallMode; Components:vst2_64; Flags: ignoreversion; 35 | 36 | Source: "..\build-win\vst3\Win32\bin\Synthesis.vst3"; DestDir: "{cf}\VST3\"; Check: not Is64BitInstallMode; Components:vst3_32; Flags: ignoreversion; 37 | Source: "..\build-win\vst3\Win32\bin\Synthesis.vst3"; DestDir: "{cf32}\VST3\"; Check: Is64BitInstallMode; Components:vst3_32; Flags: ignoreversion; 38 | Source: "..\build-win\vst3\x64\bin\Synthesis.vst3"; DestDir: "{cf64}\VST3\"; Check: Is64BitInstallMode; Components:vst3_64; Flags: ignoreversion; 39 | 40 | Source: "..\build-win\rtas\bin\Synthesis.dpm"; DestDir: "{cf32}\Digidesign\DAE\Plug-Ins\"; Components:rtas_32; Flags: ignoreversion; 41 | Source: "..\build-win\rtas\bin\Synthesis.dpm.rsr"; DestDir: "{cf32}\Digidesign\DAE\Plug-Ins\"; Components:rtas_32; Flags: ignoreversion; 42 | 43 | Source: "..\build-win\aax\bin\Synthesis.aaxplugin\*.*"; DestDir: "{cf32}\Avid\Audio\Plug-Ins\Synthesis.aaxplugin\"; Components:aax_32; Flags: ignoreversion recursesubdirs; 44 | 45 | Source: "..\manual\Synthesis_manual.pdf"; DestDir: "{app}" 46 | Source: "changelog.txt"; DestDir: "{app}" 47 | Source: "readmewin.rtf"; DestDir: "{app}"; DestName: "readme.rtf"; Flags: isreadme 48 | 49 | [Icons] 50 | Name: "{group}\Synthesis"; Filename: "{app}\Synthesis.exe" 51 | Name: "{group}\User guide"; Filename: "{app}\Synthesis_manual.pdf" 52 | Name: "{group}\Changelog"; Filename: "{app}\changelog.txt" 53 | ;Name: "{group}\readme"; Filename: "{app}\readme.rtf" 54 | Name: "{group}\Uninstall Synthesis"; Filename: "{app}\unins000.exe" 55 | 56 | ;[Dirs] 57 | ;Name: {cf}\Digidesign\DAE\Plugins\ 58 | 59 | [Code] 60 | var 61 | OkToCopyLog : Boolean; 62 | VST2DirPage_32: TInputDirWizardPage; 63 | VST2DirPage_64: TInputDirWizardPage; 64 | 65 | procedure InitializeWizard; 66 | begin 67 | if IsWin64 then begin 68 | VST2DirPage_64 := CreateInputDirPage(wpSelectDir, 69 | 'Confirm 64-Bit VST2 Plugin Directory', '', 70 | 'Select the folder in which setup should install the 64-bit VST2 Plugin, then click Next.', 71 | False, ''); 72 | VST2DirPage_64.Add(''); 73 | VST2DirPage_64.Values[0] := ExpandConstant('{reg:HKLM\SOFTWARE\VST,VSTPluginsPath|{pf}\Steinberg\VSTPlugins}\'); 74 | 75 | VST2DirPage_32 := CreateInputDirPage(wpSelectDir, 76 | 'Confirm 32-Bit VST2 Plugin Directory', '', 77 | 'Select the folder in which setup should install the 32-bit VST2 Plugin, then click Next.', 78 | False, ''); 79 | VST2DirPage_32.Add(''); 80 | VST2DirPage_32.Values[0] := ExpandConstant('{reg:HKLM\SOFTWARE\WOW6432NODE\VST,VSTPluginsPath|{pf32}\Steinberg\VSTPlugins}\'); 81 | end else begin 82 | VST2DirPage_32 := CreateInputDirPage(wpSelectDir, 83 | 'Confirm 32-Bit VST2 Plugin Directory', '', 84 | 'Select the folder in which setup should install the 32-bit VST2 Plugin, then click Next.', 85 | False, ''); 86 | VST2DirPage_32.Add(''); 87 | VST2DirPage_32.Values[0] := ExpandConstant('{reg:HKLM\SOFTWARE\VST,VSTPluginsPath|{pf}\Steinberg\VSTPlugins}\'); 88 | end; 89 | end; 90 | 91 | function GetVST2Dir_32(Param: String): String; 92 | begin 93 | Result := VST2DirPage_32.Values[0] 94 | end; 95 | 96 | function GetVST2Dir_64(Param: String): String; 97 | begin 98 | Result := VST2DirPage_64.Values[0] 99 | end; 100 | 101 | procedure CurStepChanged(CurStep: TSetupStep); 102 | begin 103 | if CurStep = ssDone then 104 | OkToCopyLog := True; 105 | end; 106 | 107 | procedure DeinitializeSetup(); 108 | begin 109 | if OkToCopyLog then 110 | FileCopy (ExpandConstant ('{log}'), ExpandConstant ('{app}\InstallationLogFile.log'), FALSE); 111 | RestartReplace (ExpandConstant ('{log}'), ''); 112 | end; 113 | 114 | [UninstallDelete] 115 | Type: files; Name: "{app}\InstallationLogFile.log" -------------------------------------------------------------------------------- /installer/changelog.txt: -------------------------------------------------------------------------------- 1 | Synthesis changelog 2 | www.olilarkin.co.uk 3 | 4 | 00/00/00 - v1.00 initial release -------------------------------------------------------------------------------- /installer/intro.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 2 | {\fonttbl\f0\fnil\fcharset0 LucidaGrande;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww14440\viewh8920\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural 6 | 7 | \f0\fs26 \cf0 I hope you enjoy using Synthesis as much as I did making it. Please let me know how you use it and if you make any interesting recordings, I'd love to hear them.\ 8 | \ 9 | Oli Larkin\ 10 | \ 11 | contact@olilarkin.co.uk\ 12 | \ 13 | http://www.olilarkin.co.uk\ 14 | \ 15 | http://soundcloud.com/olilarkin} -------------------------------------------------------------------------------- /installer/license.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360 2 | {\fonttbl\f0\fswiss\fcharset0 ArialMT;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww17060\viewh12300\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural 6 | 7 | \f0\b\fs20 \cf0 Caveat: 8 | \b0 \ 9 | By installing this software you agree to use it at your own risk. The developer cannot be held responsible for any damages caused as a result of it's use.\ 10 | \ 11 | 12 | \b Distribution: 13 | \b0 \ 14 | You are not permitted to distribute the software without the developer's permission. This includes, but is not limited to the distribution on magazine covers or software review websites.\ 15 | \ 16 | 17 | \b Multiple Installations*: 18 | \b0 If you purchased this product as an individual, you are licensed to install and use the software on any computer you need to use it on, providing you remove it afterwards (if it is a shared machine). If you purchased it as an institution or company, you are licensed to use it on one machine only, and must purchase additional copies for each machine you wish to use it on.\ 19 | \ 20 | 21 | \b Upgrades*: 22 | \b0 If you purchased this product you are entitled to free updates until the next major version number. The developer makes no guarantee is made that this product will be maintained indefinitely.\ 23 | \ 24 | 25 | \b License transfers*: 26 | \b0 If you purchased this product you may transfer your license to another person. As the original owner you are required to contact the developer with the details of the license transfer, so that the new owner can receive the updates and support attached to the license. Upon transferring a license the original owner must remove any copies from their machines and are no longer permitted to use the software.\ 27 | \ 28 | 29 | \b Synthesis is \'a9 Copyright Oliver Larkin 2004-2011\ 30 | 31 | \b0 \ 32 | http://www.olilarkin.co.uk\ 33 | \ 34 | VST and VST3 are trademarks of Steinberg Media Technologies GmbH. \ 35 | Audio Unit is a trademark of Apple, Inc. \ 36 | RTAS and AAX are trademarks of Avid, Inc.\ 37 | \ 38 | * Applies to full version only, not the demo version.} -------------------------------------------------------------------------------- /installer/readmeosx.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1138 2 | {\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \paperw11900\paperh16840\margl1440\margr1440\vieww14320\viewh8340\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural 6 | 7 | \f0\fs26 \cf0 The plugins will be installed in your system plugin folders which will make them available to all user accounts on your computer. 8 | \f1\fs20 9 | \f0\fs26 The standalone will be installed in the system Applications folder. \ 10 | \ 11 | If you don't want to install all components, click "Customize" on the "Installation Type" page.\ 12 | \ 13 | The plugins and app support both 32bit and 64bit operation.\ 14 | \ 15 | If you experience any problems with Synthesis, please contact me at the following address:\ 16 | \ 17 | support@olilarkin.co.uk} -------------------------------------------------------------------------------- /installer/readmewin.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 LucidaGrande;}} 2 | {\*\generator Msftedit 5.41.15.1515;}\viewkind4\uc1\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\lang2057\b\f0\fs26 Thanks for installing Synthesis\b0\par 3 | \par 4 | I hope you enjoy using Synthesis as much as I did making it. Please let me know how you use it and if you make any interesting recordings, I'd love to hear them.\par 5 | \par 6 | Oli Larkin\par 7 | \par 8 | contact@olilarkin.co.uk\par 9 | http://www.olilarkin.co.uk\par 10 | http://soundcloud.com/olilarkin\par 11 | \par 12 | If you experience any problems with Synthesis, please contact me at the following address:\par 13 | \par 14 | \pard\b support@olilarkin.co.uk\b0\par 15 | } 16 | -------------------------------------------------------------------------------- /makedist-mac.command: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | BASEDIR=$(dirname $0) 4 | 5 | # AAX codesigning requires ashelper tool in /usr/local/bin and aax.key/.crt in ./../../../Certificates/ 6 | 7 | 8 | cd $BASEDIR 9 | 10 | #--------------------------------------------------------------------------------------------------------- 11 | 12 | #variables 13 | 14 | VERSION=`echo | grep PLUG_VER resource.h` 15 | VERSION=${VERSION//\#define PLUG_VER } 16 | VERSION=${VERSION//\'} 17 | MAJOR_VERSION=$(($VERSION & 0xFFFF0000)) 18 | MAJOR_VERSION=$(($MAJOR_VERSION >> 16)) 19 | MINOR_VERSION=$(($VERSION & 0x0000FF00)) 20 | MINOR_VERSION=$(($MINOR_VERSION >> 8)) 21 | BUG_FIX=$(($VERSION & 0x000000FF)) 22 | 23 | FULL_VERSION=$MAJOR_VERSION"."$MINOR_VERSION"."$BUG_FIX 24 | 25 | # work out the paths to the bundles 26 | 27 | VST2=`echo | grep VST_FOLDER ../../common.xcconfig` 28 | VST2=${VST2//\VST_FOLDER = }/Synthesis.vst 29 | 30 | VST3=`echo | grep VST3_FOLDER ../../common.xcconfig` 31 | VST3=${VST3//\VST3_FOLDER = }/Synthesis.vst3 32 | 33 | AU=`echo | grep AU_FOLDER ../../common.xcconfig` 34 | AU=${AU//\AU_FOLDER = }/Synthesis.component 35 | 36 | APP=`echo | grep APP_FOLDER ../../common.xcconfig` 37 | APP=${APP//\APP_FOLDER = }/Synthesis.app 38 | 39 | # Dev build folder 40 | RTAS=`echo | grep RTAS_FOLDER ../../common.xcconfig` 41 | RTAS=${RTAS//\RTAS_FOLDER = }/Synthesis.dpm 42 | RTAS_FINAL="/Library/Application Support/Digidesign/Plug-Ins/Synthesis.dpm" 43 | 44 | # Dev build folder 45 | AAX=`echo | grep AAX_FOLDER ../../common.xcconfig` 46 | AAX=${AAX//\AAX_FOLDER = }/Synthesis.aaxplugin 47 | AAX_FINAL="/Library/Application Support/Avid/Audio/Plug-Ins/Synthesis.aaxplugin" 48 | 49 | PKG='installer/build-mac/Synthesis Installer.pkg' 50 | PKG_US='installer/build-mac/Synthesis Installer.unsigned.pkg' 51 | 52 | CERT_ID=`echo | grep CERTIFICATE_ID ../../common.xcconfig` 53 | CERT_ID=${CERT_ID//\CERTIFICATE_ID = } 54 | 55 | echo "making Synthesis version $FULL_VERSION mac distribution..." 56 | echo "" 57 | 58 | #--------------------------------------------------------------------------------------------------------- 59 | 60 | ./update_version.py 61 | 62 | #could use touch to force a rebuild 63 | #touch blah.h 64 | 65 | #--------------------------------------------------------------------------------------------------------- 66 | 67 | #remove existing dist folder 68 | #if [ -d installer/dist ] 69 | #then 70 | # rm -R installer/dist 71 | #fi 72 | 73 | #mkdir installer/dist 74 | 75 | #remove existing binaries 76 | if [ -d $APP ] 77 | then 78 | sudo rm -f -R -f $APP 79 | fi 80 | 81 | if [ -d $AU ] 82 | then 83 | sudo rm -f -R $AU 84 | fi 85 | 86 | if [ -d $VST2 ] 87 | then 88 | sudo rm -f -R $VST2 89 | fi 90 | 91 | if [ -d $VST3 ] 92 | then 93 | sudo rm -f -R $VST3 94 | fi 95 | 96 | if [ -d "${RTAS}" ] 97 | then 98 | sudo rm -f -R "${RTAS}" 99 | fi 100 | 101 | if [ -d "${RTAS_FINAL}" ] 102 | then 103 | sudo rm -f -R "${RTAS_FINAL}" 104 | fi 105 | 106 | if [ -d "${AAX}" ] 107 | then 108 | sudo rm -f -R "${AAX}" 109 | fi 110 | 111 | if [ -d "${AAX_FINAL}" ] 112 | then 113 | sudo rm -f -R "${AAX_FINAL}" 114 | fi 115 | 116 | #--------------------------------------------------------------------------------------------------------- 117 | 118 | # build xcode project. Change target to build individual formats 119 | xcodebuild -project Synthesis.xcodeproj -xcconfig Synthesis.xcconfig -target "All" -configuration Release 2> ./build-mac.log 120 | #xcodebuild -project Synthesis-ios.xcodeproj -xcconfig Synthesis.xcconfig -target "IOSAPP" -configuration Release 121 | 122 | if [ -s build-mac.log ] 123 | then 124 | echo "build failed due to following errors:" 125 | echo "" 126 | cat build-mac.log 127 | exit 1 128 | else 129 | rm build-mac.log 130 | fi 131 | 132 | #--------------------------------------------------------------------------------------------------------- 133 | 134 | #icon stuff - http://maxao.free.fr/telechargements/setfileicon.gz 135 | echo "setting icons" 136 | echo "" 137 | setfileicon resources/Synthesis.icns $AU 138 | setfileicon resources/Synthesis.icns $VST2 139 | setfileicon resources/Synthesis.icns $VST3 140 | setfileicon resources/Synthesis.icns "${RTAS}" 141 | setfileicon resources/Synthesis.icns "${AAX}" 142 | 143 | #--------------------------------------------------------------------------------------------------------- 144 | 145 | #ProTools stuff 146 | 147 | echo "copying RTAS bundle from 3PDev to main RTAS folder" 148 | sudo cp -p -R "${RTAS}" "${RTAS_FINAL}" 149 | 150 | echo "copying AAX bundle from 3PDev to main AAX folder" 151 | sudo cp -p -R "${AAX}" "${AAX_FINAL}" 152 | 153 | echo "code sign AAX binary" 154 | sudo ashelper -f "${AAX_FINAL}/Contents/MacOS/Synthesis" -l ../../../Certificates/aax.crt -k ../../../Certificates/aax.key -o "${AAX_FINAL}/Contents/MacOS/Synthesis" 155 | #--------------------------------------------------------------------------------------------------------- 156 | 157 | #appstore stuff 158 | 159 | # echo "code signing app for appstore" 160 | # echo "" 161 | # codesign -f -s "3rd Party Mac Developer Application: ""${CERT_ID}" $APP --entitlements resources/Synthesis.entitlements 162 | # 163 | # echo "building pkg for app store" 164 | # productbuild \ 165 | # --component $APP /Applications \ 166 | # --sign "3rd Party Mac Developer Installer: ""${CERT_ID}" \ 167 | # --product "/Applications/Synthesis.app/Contents/Info.plist" installer/Synthesis.pkg 168 | 169 | #--------------------------------------------------------------------------------------------------------- 170 | 171 | #10.8 Gatekeeper/Developer ID stuff 172 | 173 | #echo "code sign app for Gatekeeper on 10.8" 174 | #echo "" 175 | #codesign -f -s "Developer ID Application: ""${CERT_ID}" $APP 176 | 177 | #--------------------------------------------------------------------------------------------------------- 178 | 179 | # installer, uses Packages http://s.sudre.free.fr/Software/Packages/about.html 180 | sudo sudo rm -R -f installer/Synthesis-mac.dmg 181 | 182 | echo "building installer" 183 | echo "" 184 | packagesbuild installer/Synthesis.pkgproj 185 | 186 | #echo "code sign installer for Gatekeeper on 10.8" 187 | #echo "" 188 | #mv "${PKG}" "${PKG_US}" 189 | #productsign --sign "Developer ID Installer: ""${CERT_ID}" "${PKG_US}" "${PKG}" 190 | 191 | #rm -R -f "${PKG_US}" 192 | 193 | #set installer icon 194 | setfileicon resources/Synthesis.icns "${PKG}" 195 | 196 | #--------------------------------------------------------------------------------------------------------- 197 | 198 | # dmg, can use dmgcanvas http://www.araelium.com/dmgcanvas/ to make a nice dmg 199 | 200 | echo "building dmg" 201 | echo "" 202 | 203 | if [ -d installer/Synthesis.dmgCanvas ] 204 | then 205 | dmgcanvas installer/Synthesis.dmgCanvas installer/Synthesis-mac.dmg 206 | else 207 | hdiutil create installer/Synthesis.dmg -srcfolder installer/build-mac/ -ov -anyowners -volname Synthesis 208 | 209 | if [ -f installer/Synthesis-mac.dmg ] 210 | then 211 | rm -f installer/Synthesis-mac.dmg 212 | fi 213 | 214 | hdiutil convert installer/Synthesis.dmg -format UDZO -o installer/Synthesis-mac.dmg 215 | sudo rm -R -f installer/Synthesis.dmg 216 | fi 217 | 218 | sudo rm -R -f installer/build-mac/ 219 | 220 | #--------------------------------------------------------------------------------------------------------- 221 | # zip 222 | 223 | # echo "copying binaries..." 224 | # echo "" 225 | # cp -R $AU installer/dist/Synthesis.component 226 | # cp -R $VST2 installer/dist/Synthesis.vst 227 | # cp -R $VST3 installer/dist/Synthesis.vst3 228 | # cp -R $RTAS installer/dist/Synthesis.dpm 229 | # cp -R $AAX installer/dist/Synthesis.aaxplugin 230 | # cp -R $APP installer/dist/Synthesis.app 231 | # 232 | # echo "zipping binaries..." 233 | # echo "" 234 | # ditto -c -k installer/dist installer/Synthesis-mac.zip 235 | # rm -R installer/dist 236 | 237 | #--------------------------------------------------------------------------------------------------------- 238 | 239 | echo "done" -------------------------------------------------------------------------------- /makedist-win.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | 3 | REM - batch file to build VS2010 project and zip the resulting binaries (or make installer) 4 | REM - updating version numbers requires python and python path added to %PATH% env variable 5 | REM - zipping requires 7zip in %ProgramFiles%\7-Zip\7z.exe 6 | REM - building installer requires innotsetup in "%ProgramFiles(x86)%\Inno Setup 5\iscc" 7 | REM - AAX codesigning requires ashelper tool added to %PATH% env variable and aax.key/.crt in .\..\..\..\Certificates\ 8 | 9 | echo Making Synthesis win distribution ... 10 | 11 | echo ------------------------------------------------------------------ 12 | echo Updating version numbers ... 13 | 14 | call python update_version.py 15 | 16 | echo ------------------------------------------------------------------ 17 | echo Building ... 18 | 19 | if exist "%ProgramFiles(x86)%" (goto 64-Bit) else (goto 32-Bit) 20 | 21 | :32-Bit 22 | echo 32-Bit O/S detected 23 | call "%ProgramFiles%\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" 24 | goto END 25 | 26 | :64-Bit 27 | echo 64-Bit Host O/S detected 28 | call "%ProgramFiles(x86)%\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" 29 | goto END 30 | :END 31 | 32 | REM - set preprocessor macros like this, for instance to enable demo build: 33 | REM - SET CMDLINE_DEFINES="DEMO_VERSION" 34 | 35 | REM - Could build individual targets like this: 36 | REM - msbuild Synthesis-app.vcxproj /p:configuration=release /p:platform=win32 37 | 38 | msbuild Synthesis.sln /p:configuration=release /p:platform=win32 /nologo /noconsolelogger /fileLogger /v:quiet /flp:logfile=build-win.log;errorsonly 39 | msbuild Synthesis.sln /p:configuration=release /p:platform=x64 /nologo /noconsolelogger /fileLogger /v:quiet /flp:logfile=build-win.log;errorsonly;append 40 | 41 | echo ------------------------------------------------------------------ 42 | echo Code sign aax binary... 43 | call ashelper -f .\build-win\aax\bin\Synthesis.aaxplugin\Contents\Win32\Synthesis.aaxplugin -l .\..\..\..\Certificates\aax.crt -k .\..\..\..\Certificates\aax.key -o .\build-win\aax\bin\Synthesis.aaxplugin\Contents\Win32\Synthesis.aaxplugin 44 | REM - call ashelper -f .\build-win\aax\bin\Synthesis.aaxplugin\Contents\x64\Synthesis.aaxplugin -l .\..\..\..\Certificates\aax.crt -k .\..\..\..\Certificates\aax.key -o .\build-win\aax\bin\Synthesis.aaxplugin\Contents\x64\Synthesis.aaxplugin 45 | 46 | REM - Make Installer (InnoSetup) 47 | 48 | echo ------------------------------------------------------------------ 49 | echo Making Installer ... 50 | 51 | if exist "%ProgramFiles(x86)%" (goto 64-Bit-is) else (goto 32-Bit-is) 52 | 53 | :32-Bit-is 54 | "%ProgramFiles%\Inno Setup 5\iscc" /cc ".\installer\Synthesis.iss" 55 | goto END-is 56 | 57 | :64-Bit-is 58 | "%ProgramFiles(x86)%\Inno Setup 5\iscc" /cc ".\installer\Synthesis.iss" 59 | goto END-is 60 | 61 | :END-is 62 | 63 | REM - ZIP 64 | REM - "%ProgramFiles%\7-Zip\7z.exe" a .\installer\Synthesis-win-32bit.zip .\build-win\app\win32\bin\Synthesis.exe .\build-win\vst3\win32\bin\Synthesis.vst3 .\build-win\vst2\win32\bin\Synthesis.dll .\build-win\rtas\bin\Synthesis.dpm .\build-win\rtas\bin\Synthesis.dpm.rsr .\build-win\aax\bin\Synthesis.aaxplugin* .\installer\license.rtf .\installer\readmewin.rtf 65 | REM - "%ProgramFiles%\7-Zip\7z.exe" a .\installer\Synthesis-win-64bit.zip .\build-win\app\x64\bin\Synthesis.exe .\build-win\vst3\x64\bin\Synthesis.vst3 .\build-win\vst2\x64\bin\Synthesis.dll .\installer\license.rtf .\installer\readmewin.rtf 66 | 67 | echo ------------------------------------------------------------------ 68 | echo Printing log file to console... 69 | 70 | type build-win.log 71 | 72 | pause -------------------------------------------------------------------------------- /manual/Synthesis_manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/manual/Synthesis_manual.pdf -------------------------------------------------------------------------------- /opencl_kernels.cl: -------------------------------------------------------------------------------- 1 | __kernel void oscillator(__global const float *voicesDataBuffer, 2 | __global const float *voicesEnergyBuffer, 3 | __global const float *instrumentDataBuffer, 4 | float mModPrevious, 5 | float mModCurrent, 6 | float mB, 7 | float partialDetuneRange, 8 | float mTimeStep, 9 | short NUM_PARTIALS, 10 | short BLOCK_SIZE, 11 | short NUM_CHANNELS, 12 | __global float *voicesSampleBuffer 13 | ) { 14 | 15 | int globalID = get_global_id(0); 16 | short voiceID = globalID / BLOCK_SIZE; // find which voice # this work-item is calculating a sample for 17 | float mTime = voicesDataBuffer[voiceID*5]; 18 | int sampleIndex = globalID - (BLOCK_SIZE*voiceID);// sample index/offset within this voice (never higher than BLOCK_SIZE-1) 19 | mTime += mTimeStep * (float)sampleIndex; // find actual time value for this sample 20 | float mFrequency = voicesDataBuffer[voiceID*5+1]; 21 | float mVelocity = (float)voicesDataBuffer[voiceID*5+2]; 22 | float randStringMult = voicesDataBuffer[voiceID*5+3]; 23 | short x = (short)voicesDataBuffer[voiceID*5+4]; // random seed 24 | float mEnergy = voicesEnergyBuffer[voiceID*BLOCK_SIZE + sampleIndex]; 25 | 26 | // re-center mod wheel values around 0 27 | // mModPrevious = mModPrevious - 0.5f; 28 | // mModCurrent = mModCurrent - 0.5f; 29 | 30 | // linear 31 | // float mMod = mModPrevious + sampleIndex * (mModCurrent - mModPrevious) / (BLOCK_SIZE - 1); 32 | 33 | float xVal = convert_float(sampleIndex)/convert_float(BLOCK_SIZE); // scale sampleIndex/BLOCK_SIZE to (0,1) value 34 | 35 | // smoothstep 36 | xVal = xVal * xVal * (3.0f - 2.0f * xVal); 37 | float mMod = mModPrevious + (mModCurrent - mModPrevious) * xVal; // the first bit re-scales the output, and the last bit is the cubic interp function 38 | 39 | // smootherstep 40 | // xVal = xVal*xVal*xVal*(xVal*(xVal*6.0f - 15.0f) + 10.0f); 41 | // float mMod = mModPrevious + (mModCurrent - mModPrevious) * xVal; 42 | 43 | 44 | // re-center mod around 0 45 | mMod = mMod - 0.5f; 46 | 47 | // no interpolation 48 | // float mMod = mModCurrent - 0.5f; 49 | 50 | 51 | float mLinearTerm = instrumentDataBuffer[0]; 52 | float mSquaredTerm = instrumentDataBuffer[1]; 53 | float mCubicTerm = instrumentDataBuffer[2]; 54 | float mBrightnessA = 1.0f - instrumentDataBuffer[3]; 55 | float mBrightnessB = 10000.0f * instrumentDataBuffer[4]; 56 | 57 | float mPitchBendCoarse = 2.0f * instrumentDataBuffer[5]; // (0, 2) 58 | // mPitchBendCoarse += 0.03f * mMod; // use mod wheel as pitch bend for smooth vibrato testing 59 | float mPitchBendFine = 0.02f * instrumentDataBuffer[6]; // (0, 0.02) 60 | // mPitchBendFine += (0.02f * (mMod)); // use mod wheel as pitch bend for smooth vibrato testing 61 | 62 | // mPitchBendCoarse = 1.0f; 63 | // mPitchBendFine = 0.01f; 64 | 65 | // if (sampleIndex == 0) { 66 | // printf("\n----------\n"); 67 | // } 68 | // printf("%f\n", mMod); 69 | 70 | if ((int)(22050.0f / mFrequency) < NUM_PARTIALS) { // was 22050 71 | NUM_PARTIALS = (int)(22050.0f / mFrequency); // was 22050 72 | }; // scale down num_partials to only the MAX number actually needed for this note, but don't go over the MAX partials (e.g. 128), since a 50Hz note, for example, would need 441 partials! 73 | mB *= 0.1f + mFrequency/10000.0f; // make the apparent effect of mB more linear across the octaves, so it's smaller for low notes and higher for high notes 74 | mB *= 0.1f + mFrequency*mFrequency/50000000.0f; // make the apparent effect of mB more linear across the octaves, so it's smaller for low notes and higher for high notes... in an exponential fashion, so gets much larger faster with higher frequencies 75 | mB *= 1.01f / (1.01f - (mVelocity/(1.0f+mTime*10.0f)) / 5.0f); // scales mB with velocity -- the harder you hit, the more non-linear the partials become! but this effect only lasts a brief moment (while the string is majorly deformed from the impact). // mTime's multiplicand governs how fast mB changes in response to velocity -- 1.0f is slow drop, 10.0f is much faster drop. // the final divisor governs how STRONGLY mB changes in response to velocity. 1.0 is fairly strong, while 2.0 is not nearly as strong, and 10.0 is hardly any change at all. 76 | 77 | // VECTOR VERSION (FLOAT4) 78 | 79 | float4 freqs; 80 | float4 valuesOne; 81 | float4 valuesTwo; 82 | float4 eyes; 83 | float4 amps; 84 | 85 | float sampleL = 0.0f; 86 | float sampleR = 0.0f; 87 | 88 | float4 rands; 89 | 90 | //float partialDetuneRange = 1.0f; // modulate the 1.0f to be the partialDetuneRange knob - 0.5f is very subtle, 2.0f is much bigger. 91 | 92 | partialDetuneRange /= 7000000.0f; 93 | 94 | for (int i = 0; i < NUM_PARTIALS; i+=4) { 95 | 96 | // xorshift deterministic RNG 97 | // generate 4 random numbers (to use as partial frequency multipliers and random pan values) 98 | 99 | x = x ^ (x << 21); 100 | x = x ^ (x >> 35); 101 | x = x ^ (x << 4); 102 | rands.s0 = (float)x * partialDetuneRange + 1.0f; // 10,000,000 is very subtle 103 | x = x ^ (x << 21); 104 | x = x ^ (x >> 35); 105 | x = x ^ (x << 4); 106 | rands.s1 = (float)x * partialDetuneRange + 1.0f; 107 | x = x ^ (x << 21); 108 | x = x ^ (x >> 35); 109 | x = x ^ (x << 4); 110 | rands.s2 = (float)x * partialDetuneRange + 1.0f; 111 | x = x ^ (x << 21); 112 | x = x ^ (x >> 35); 113 | x = x ^ (x << 4); 114 | rands.s3 = (float)x * partialDetuneRange + 1.0f; 115 | 116 | eyes.s0 = (float)i + 1.0f; 117 | eyes.s1 = (float)i + 2.0f; 118 | eyes.s2 = (float)i + 3.0f; 119 | eyes.s3 = (float)i + 4.0f; 120 | 121 | 122 | // testing mod here 123 | // mFrequency += mMod; // this makes the frequency change with the mod wheel ALSO (mod wheel already changes timbre/brightness a bit) 124 | 125 | // mod wheel changes brightness/timbre subtly here 126 | freqs = (mPitchBendCoarse + mPitchBendFine * pow(eyes, 0.3f)) * eyes * mFrequency * sqrt((1.0f + mB * eyes * eyes)); // includes inharmonicity coefficient 127 | 128 | // printf("%f, %f\n", mFrequency, freqs.s3); 129 | 130 | amps = pow((mEnergy*(mLinearTerm + mEnergy*(mSquaredTerm + mEnergy*(mCubicTerm)))), (pow(eyes, mBrightnessA)+freqs/mBrightnessB)); 131 | 132 | // testing timbre envelope 133 | // amps += 0.2f * sin(freqs / 5000.0f + mMod) * mEnergy / eyes; 134 | 135 | 136 | // calculate string 1 and 2 137 | // 2pi used to be: 6.283185307179586f (but too many digits for float!) 138 | valuesOne = sin(6.2831853f * mTime * freqs * rands) * amps * ((1.0f-rands)*(75.0f/partialDetuneRange/7000000.0f)+0.7f); // the last multiplier, using rands, is for random partial amplitudes, using same rands as for partial frequency multipliers 139 | valuesTwo = sin(6.2831853f * mTime * freqs * rands * randStringMult) * amps * ((1.0f-rands)*(75.0f/partialDetuneRange/7000000.0f)+0.7f); 140 | 141 | // random white noise transient test 142 | 143 | //if (mTime < 0.100f) { 144 | valuesOne.s0 += fabs(rands.s0 - 1.0f) * pow(0.5f, mTime*50.0f) * 20.0f * mEnergy * mEnergy * (1.0f + mEnergy); 145 | //} 146 | 147 | //rands = fabs(rands-1.0f) * 214.0f; // subtract 1 to center around 0, take abs so it's positive, and make it bigger - want it be (0,1) --> 148 | rands = fabs(rands-1.0f) * 214.0f / partialDetuneRange / 7000000.0f; // subtract 1 to center around 0, take abs so it's positive, and make it bigger - want it be (0,1) --> this undoes the multiplication above at partialDetuneRange and scales the rands appropriately so they're (0,1) for L/R pan values 149 | 150 | 151 | 152 | /// reverb wash (sound starts in mono and washes out to the sides, to random pan positions, as if traveling along the soundboard) 153 | 154 | 155 | 156 | // pan speed multiplier 157 | eyes.s0 = 5.0f * mTime + 1.0f; // I'm just re-using a float variable here to save memory -- nothing relevant about eyes in these following calculations // Also, 5.0f is the pan speed multiplier -- the higher that number, the faster the pans will wash out to the sides. 5.0f is a good medium value, not too fast, not too slow. Subtle, complex, realistic. 158 | 159 | // add string 1 to left channel 160 | sampleL += valuesOne.s0 * ((1.0f-rands.s0) - (0.5f - rands.s0)/eyes.s0); 161 | sampleL += valuesOne.s1 * ((1.0f-rands.s1) - (0.5f - rands.s1)/eyes.s0); 162 | sampleL += valuesOne.s2 * ((1.0f-rands.s2) - (0.5f - rands.s2)/eyes.s0); 163 | sampleL += valuesOne.s3 * ((1.0f-rands.s3) - (0.5f - rands.s3)/eyes.s0); 164 | // add string 2 to left channel 165 | sampleL += valuesTwo.s0 * ((1.0f-rands.s2) - (0.5f - rands.s2)/eyes.s0); 166 | sampleL += valuesTwo.s1 * ((1.0f-rands.s0) - (0.5f - rands.s0)/eyes.s0); 167 | sampleL += valuesTwo.s2 * ((1.0f-rands.s3) - (0.5f - rands.s3)/eyes.s0); 168 | sampleL += valuesTwo.s3 * ((1.0f-rands.s1) - (0.5f - rands.s1)/eyes.s0); 169 | 170 | // add string 1 to right channel 171 | sampleR += valuesOne.s0 * ((rands.s0) - (rands.s0 - 0.5f)/eyes.s0); 172 | sampleR += valuesOne.s1 * ((rands.s1) - (rands.s1 - 0.5f)/eyes.s0); 173 | sampleR += valuesOne.s2 * ((rands.s2) - (rands.s2 - 0.5f)/eyes.s0); 174 | sampleR += valuesOne.s3 * ((rands.s3) - (rands.s3 - 0.5f)/eyes.s0); 175 | // add string 2 to right channel 176 | sampleR += valuesTwo.s0 * ((rands.s2) - (rands.s2 - 0.5f)/eyes.s0); 177 | sampleR += valuesTwo.s1 * ((rands.s0) - (rands.s0 - 0.5f)/eyes.s0); 178 | sampleR += valuesTwo.s2 * ((rands.s3) - (rands.s3 - 0.5f)/eyes.s0); 179 | sampleR += valuesTwo.s3 * ((rands.s1) - (rands.s1 - 0.5f)/eyes.s0); 180 | 181 | 182 | 183 | } 184 | 185 | // write this work-item's sample to global memory 186 | // only works in stereo (include an if statement to switch between stereo and mono) 187 | voicesSampleBuffer[NUM_CHANNELS * (BLOCK_SIZE * voiceID + sampleIndex)] = sampleL * 0.15f; // was * 0.03f when using amps w/o mEnergy 188 | voicesSampleBuffer[NUM_CHANNELS * (BLOCK_SIZE * voiceID + sampleIndex) + 1] = sampleR * 0.15f; // was * 0.03f when using amps w/o mEnergy 189 | } 190 | 191 | 192 | __kernel void add_voices(__global float *voicesSampleBuffer, short NUM_ACTIVE_VOICES, short BLOCK_SIZE, short NUM_CHANNELS, __global float *outputSampleBuffer) { 193 | 194 | int globalID = get_global_id(0); 195 | float sample = 0.0f; 196 | 197 | // this adder kernel - first work-item adds up first sample of left channel of voice 1, voice 2, etc., second work-item adds up first sample of right channel of voice 1, voice 2, etc.,... 198 | 199 | for (short i = 0; i < NUM_ACTIVE_VOICES; i++) { 200 | sample += voicesSampleBuffer[i * BLOCK_SIZE * NUM_CHANNELS + globalID]; 201 | } 202 | // write back to global memory 203 | outputSampleBuffer[globalID] = sample; 204 | } -------------------------------------------------------------------------------- /reaper-project-au.RPP: -------------------------------------------------------------------------------- 1 | 26 | 28 | RENDER_FILE "" 29 | RENDER_PATTERN "" 30 | RENDER_FMT 0 2 0 31 | RENDER_1X 0 32 | RENDER_RANGE 1 0.00000000000000 0.00000000000000 33 | RENDER_RESAMPLE 3 0 1 34 | RENDER_ADDTOPROJ 0 35 | RENDER_STEMS 0 36 | RENDER_DITHER 0 37 | TIMELOCKMODE 1 38 | TEMPOENVLOCKMODE 1 39 | ITEMMIX 0 40 | DEFPITCHMODE 393216 41 | TAKELANE 1 42 | SAMPLERATE 44100 0 0 43 | 45 | LOCK 1 46 | 52 | GLOBAL_AUTO -1 53 | TEMPO 120.00000000000000 4 4 54 | PLAYRATE 1.00000000000000 0 0.25000 4.00000 55 | SELECTION 0.00000000000000 2.80063492063492 56 | SELECTION2 0.00000000000000 2.80063492063492 57 | MASTERAUTOMODE 0 58 | MASTERTRACKHEIGHT 0 59 | MASTERPEAKCOL 16576 60 | MASTERMUTESOLO 0 61 | MASTERTRACKVIEW 0 0.666700 0.500000 0.500000 -1 -1 -1 62 | MASTERHWOUT 0 0 1.00000000000000 0.00000000000000 0 0 0 -1.00000000000000 63 | MASTER_NCH 2 2 64 | MASTER_VOLUME 1.00000000000000 0.00000000000000 -1.00000000000000 -1.00000000000000 1.00000000000000 65 | MASTER_FX 1 66 | MASTER_SEL 0 67 | 74 | 81 | 83 | 120 | FLOATPOS 0 0 0 0 121 | FXID {18380C3F-E136-AA48-B17F-331475C8D551} 122 | WAK 0 123 | > 124 | 145 | > 146 | > 147 | > 148 | -------------------------------------------------------------------------------- /reaper-project-au.RPP-bak: -------------------------------------------------------------------------------- 1 | 26 | 28 | RENDER_FILE "" 29 | RENDER_PATTERN "" 30 | RENDER_FMT 0 2 0 31 | RENDER_1X 0 32 | RENDER_RANGE 1 0.00000000000000 0.00000000000000 33 | RENDER_RESAMPLE 3 0 1 34 | RENDER_ADDTOPROJ 0 35 | RENDER_STEMS 0 36 | RENDER_DITHER 0 37 | TIMELOCKMODE 1 38 | TEMPOENVLOCKMODE 1 39 | ITEMMIX 0 40 | DEFPITCHMODE 393216 41 | TAKELANE 1 42 | SAMPLERATE 44100 0 0 43 | 45 | LOCK 1 46 | 52 | GLOBAL_AUTO -1 53 | TEMPO 120.00000000000000 4 4 54 | PLAYRATE 1.00000000000000 0 0.25000 4.00000 55 | SELECTION 0.00000000000000 2.80063492063492 56 | SELECTION2 0.00000000000000 2.80063492063492 57 | MASTERAUTOMODE 0 58 | MASTERTRACKHEIGHT 0 59 | MASTERPEAKCOL 16576 60 | MASTERMUTESOLO 0 61 | MASTERTRACKVIEW 0 0.666700 0.500000 0.500000 -1 -1 -1 62 | MASTERHWOUT 0 0 1.00000000000000 0.00000000000000 0 0 0 -1.00000000000000 63 | MASTER_NCH 0 2 64 | MASTER_VOLUME 1.00000000000000 0.00000000000000 -1.00000000000000 -1.00000000000000 1.00000000000000 65 | MASTER_FX 1 66 | MASTER_SEL 0 67 | 74 | 81 | 83 | 115 | FLOATPOS 0 0 0 0 116 | FXID {589A9652-3825-4A41-AC98-13EE7B68CF29} 117 | WAK 0 118 | > 119 | 140 | > 141 | > 142 | > 143 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | #define PLUG_MFR "DevinMooers" 2 | #define PLUG_NAME "Synthesis" 3 | 4 | #define PLUG_CLASS_NAME Synthesis 5 | 6 | #define BUNDLE_MFR "DevinMooers" 7 | #define BUNDLE_NAME "Synthesis" 8 | 9 | #define PLUG_ENTRY Synthesis_Entry 10 | #define PLUG_VIEW_ENTRY Synthesis_ViewEntry 11 | 12 | #define PLUG_ENTRY_STR "Synthesis_Entry" 13 | #define PLUG_VIEW_ENTRY_STR "Synthesis_ViewEntry" 14 | 15 | #define VIEW_CLASS Synthesis_View 16 | #define VIEW_CLASS_STR "Synthesis_View" 17 | 18 | // Format 0xMAJR.MN.BG - in HEX! so version 10.1.5 would be 0x000A0105 19 | #define PLUG_VER 0x00010000 20 | #define VST3_VER_STR "1.0.0" 21 | 22 | // http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm 23 | // 4 chars, single quotes. At least one capital letter 24 | #define PLUG_UNIQUE_ID 'Ipef' 25 | // make sure this is not the same as BUNDLE_MFR 26 | #define PLUG_MFR_ID 'Acme' 27 | 28 | // ProTools stuff 29 | 30 | #if (defined(AAX_API) || defined(RTAS_API)) && !defined(_PIDS_) 31 | #define _PIDS_ 32 | const int PLUG_TYPE_IDS[2] = {'EFN1', 'EFN2'}; 33 | const int PLUG_TYPE_IDS_AS[2] = {'EFA1', 'EFA2'}; // AudioSuite 34 | #endif 35 | 36 | #define PLUG_MFR_PT "DevinMooers\nDevinMooers\nAcme" 37 | #define PLUG_NAME_PT "Synthesis\nIPEF" 38 | #define PLUG_TYPE_PT "Effect" 39 | #define PLUG_DOES_AUDIOSUITE 1 40 | 41 | /* PLUG_TYPE_PT can be "None", "EQ", "Dynamics", "PitchShift", "Reverb", "Delay", "Modulation", 42 | "Harmonic" "NoiseReduction" "Dither" "SoundField" "Effect" 43 | instrument determined by PLUG _IS _INST 44 | */ 45 | 46 | // #define PLUG_CHANNEL_IO "1-1 2-2" 47 | #if (defined(AAX_API) || defined(RTAS_API)) 48 | #define PLUG_CHANNEL_IO "1-1 2-2" 49 | #else 50 | // no audio input. mono or stereo output 51 | // The 0-1 0-2 means that there's either no input and one output (mono) (0-1) or no input and two outputs (stereo) (0-2). 52 | #define PLUG_CHANNEL_IO "0-1 0-2" 53 | #endif 54 | 55 | #define PLUG_LATENCY 0 56 | #define PLUG_IS_INST 1 // is this is an instrument plugin? 57 | 58 | // if this is 0 RTAS can't get tempo info 59 | #define PLUG_DOES_MIDI 1 60 | 61 | #define PLUG_DOES_STATE_CHUNKS 0 62 | 63 | // Unique IDs for each image resource. 64 | #define BG_ID 101 65 | #define WHITE_KEY_ID 102 66 | #define BLACK_KEY_ID 103 67 | #define WAVEFORM_ID 104 68 | #define KNOB_ID 105 69 | 70 | // Image resource locations for this plug. 71 | #define BG_FN "resources/img/bg.png" 72 | #define WHITE_KEY_FN "resources/img/whitekey.png" 73 | #define BLACK_KEY_FN "resources/img/blackkey.png" 74 | #define WAVEFORM_FN "resources/img/waveform.png" 75 | #define KNOB_FN "resources/img/knob.png" 76 | 77 | // GUI default dimensions 78 | #define GUI_WIDTH 1000 79 | #define GUI_HEIGHT 800 80 | 81 | // Spectrogram dimensions 82 | #define SPECTROGRAM_WIDTH 600 83 | #define SPECTROGRAM_HEIGHT 300 84 | 85 | // Oscilloscope dimensions 86 | #define OSCILLOSCOPE_WIDTH 600 87 | #define OSCILLOSCOPE_HEIGHT 300 88 | 89 | // on MSVC, you must define SA_API in the resource editor preprocessor macros as well as the c++ ones 90 | #if defined(SA_API) && !defined(OS_IOS) 91 | #include "app_wrapper/app_resource.h" 92 | #endif 93 | 94 | // vst3 stuff 95 | #define MFR_URL "www.olilarkin.co.uk" 96 | #define MFR_EMAIL "spam@me.com" 97 | //#define EFFECT_TYPE_VST3 "Fx" 98 | #define EFFECT_TYPE_VST3 "Instrument|Synth" 99 | 100 | /* "Fx|Analyzer"", "Fx|Delay", "Fx|Distortion", "Fx|Dynamics", "Fx|EQ", "Fx|Filter", 101 | "Fx", "Fx|Instrument", "Fx|InstrumentExternal", "Fx|Spatial", "Fx|Generator", 102 | "Fx|Mastering", "Fx|Modulation", "Fx|PitchShift", "Fx|Restoration", "Fx|Reverb", 103 | "Fx|Surround", "Fx|Tools", "Instrument", "Instrument|Drum", "Instrument|Sampler", 104 | "Instrument|Synth", "Instrument|Synth|Sampler", "Instrument|External", "Spatial", 105 | "Spatial|Fx", "OnlyRT", "OnlyOfflineProcess", "Mono", "Stereo", 106 | "Surround" 107 | */ 108 | -------------------------------------------------------------------------------- /resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /resources/Synthesis-AAX-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${BINARY_NAME} 9 | CFBundleGetInfoString 10 | 1.0.0, Copyright DevinMooers, 2012 11 | CFBundleIdentifier 12 | com.DevinMooers.aax.${BINARY_NAME} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${BINARY_NAME} 17 | CFBundlePackageType 18 | TDMw 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleSignature 22 | PTul 23 | CFBundleVersion 24 | 1.0.0 25 | LSMultipleInstancesProhibited 26 | true 27 | LSPrefersCarbon 28 | 29 | NSAppleScriptEnabled 30 | No 31 | 32 | 33 | -------------------------------------------------------------------------------- /resources/Synthesis-AU-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${BINARY_NAME} 9 | CFBundleGetInfoString 10 | 1.0.0, Copyright DevinMooers, 2012 11 | CFBundleIdentifier 12 | com.DevinMooers.audiounit.${BINARY_NAME} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${BINARY_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleSignature 22 | Acme 23 | CFBundleVersion 24 | 1.0.0 25 | LSMinimumSystemVersion 26 | 10.5.0 27 | NSPrincipalClass 28 | Synthesis_View 29 | 30 | 31 | -------------------------------------------------------------------------------- /resources/Synthesis-OSXAPP-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${BINARY_NAME} 9 | CFBundleGetInfoString 10 | 1.0.0, Copyright DevinMooers, 2012 11 | CFBundleIconFile 12 | ${BINARY_NAME}.icns 13 | CFBundleIdentifier 14 | com.DevinMooers.standalone.${BINARY_NAME} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${BINARY_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0.0 23 | CFBundleSignature 24 | Acme 25 | CFBundleVersion 26 | 1.0.0 27 | LSApplicationCategoryType 28 | public.app-category.music 29 | LSMinimumSystemVersion 30 | 10.5.0 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | SWELLApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /resources/Synthesis-Pages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Synthesis by DevinMooers. 6 | PageTable 1 7 | 8 | 9 | 10 | 11 | 1 12 | 13 | 14 | 15 | 16 | 17 | MasterBypass 18 | 19 | 20 | 21 | 22 | 1 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | MasterBypass 31 | 32 | 33 | 34 | 35 | MasterBypass 36 | 1 37 | 38 | 1 39 | 1 40 | 1 41 | 1 42 | 1 43 | 1 44 | 1 45 | 1 46 | 1 47 | 1 48 | 1 49 | 1 50 | 1 51 | 52 | 53 | 54 | 55 | 1 56 | MasterBypass 57 | 58 | 1 59 | 1 60 | 1 61 | 1 62 | 1 63 | 1 64 | 1 65 | 1 66 | 1 67 | 1 68 | 1 69 | 1 70 | 1 71 | 72 | 73 | 74 | 75 | 1 76 | MasterBypass 77 | 78 | 1 79 | 1 80 | 1 81 | 1 82 | 1 83 | 1 84 | 1 85 | 1 86 | 1 87 | 1 88 | 1 89 | 1 90 | 1 91 | 92 | 93 | 94 | MasterBypass 95 | 1 96 | 97 | 1 98 | 1 99 | 1 100 | 1 101 | 1 102 | 1 103 | 1 104 | 1 105 | 1 106 | 1 107 | 1 108 | 1 109 | 1 110 | 111 | 112 | 113 | MasterBypass 114 | 115 | 116 | 1 117 | 118 | 119 | 120 | 121 | 122 | 123 | Ma 124 | Byp 125 | MByp 126 | Mstr Byp 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | RTAS: Synthesis 136 | 137 | 138 | 139 | 140 | MasterBypass 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /resources/Synthesis-RTAS-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${BINARY_NAME} 9 | CFBundleGetInfoString 10 | 1.0.0, Copyright DevinMooers, 2012 11 | CFBundleIdentifier 12 | com.DevinMooers.rtas.${BINARY_NAME} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${BINARY_NAME} 17 | CFBundlePackageType 18 | TDMw 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleSignature 22 | PTul 23 | CFBundleVersion 24 | 1.0.0 25 | LSMultipleInstancesProhibited 26 | true 27 | LSPrefersCarbon 28 | 29 | NSAppleScriptEnabled 30 | No 31 | 32 | 33 | -------------------------------------------------------------------------------- /resources/Synthesis-VST2-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${BINARY_NAME} 9 | CFBundleGetInfoString 10 | 1.0.0, Copyright DevinMooers, 2012 11 | CFBundleIdentifier 12 | com.DevinMooers.vst.${BINARY_NAME} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${BINARY_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleSignature 22 | Acme 23 | CFBundleVersion 24 | 1.0.0 25 | LSMinimumSystemVersion 26 | 10.5.0 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/Synthesis-VST3-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${BINARY_NAME} 9 | CFBundleGetInfoString 10 | 1.0.0, Copyright DevinMooers, 2012 11 | CFBundleIdentifier 12 | com.DevinMooers.vst3.${BINARY_NAME} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${BINARY_NAME} 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleSignature 22 | Acme 23 | CFBundleVersion 24 | 1.0.0 25 | LSMinimumSystemVersion 26 | 10.5.0 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/Synthesis.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.device.microphone 8 | 9 | com.apple.security.device.usb 10 | 11 | com.apple.security.device.firewire 12 | 13 | com.apple.security.files.user-selected.read-write 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/Synthesis.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/Synthesis.icns -------------------------------------------------------------------------------- /resources/Synthesis.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/Synthesis.ico -------------------------------------------------------------------------------- /resources/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/img/bg.png -------------------------------------------------------------------------------- /resources/img/blackkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/img/blackkey.png -------------------------------------------------------------------------------- /resources/img/knob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/img/knob.png -------------------------------------------------------------------------------- /resources/img/waveform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/img/waveform.png -------------------------------------------------------------------------------- /resources/img/whitekey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmooers/gpu-synth/e476011a3f3c3df40a90be91a706ac5e7680375c/resources/img/whitekey.png -------------------------------------------------------------------------------- /update_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # this script will update the versions in plist and installer files to match that in resource.h 4 | 5 | import plistlib, os, datetime, fileinput, glob, sys, string 6 | scriptpath = os.path.dirname(os.path.realpath(__file__)) 7 | 8 | def replacestrs(filename, s, r): 9 | files = glob.glob(filename) 10 | 11 | for line in fileinput.input(files,inplace=1): 12 | string.find(line, s) 13 | line = line.replace(s, r) 14 | sys.stdout.write(line) 15 | 16 | def main(): 17 | 18 | MajorStr = "" 19 | MinorStr = "" 20 | BugfixStr = "" 21 | 22 | for line in fileinput.input(scriptpath + "/resource.h",inplace=0): 23 | if "#define PLUG_VER " in line: 24 | FullVersion = int(string.lstrip(line, "#define PLUG_VER "), 16) 25 | major = FullVersion & 0xFFFF0000 26 | MajorStr = str(major >> 16) 27 | minor = FullVersion & 0x0000FF00 28 | MinorStr = str(minor >> 8) 29 | BugfixStr = str(FullVersion & 0x000000FF) 30 | 31 | 32 | FullVersionStr = MajorStr + "." + MinorStr + "." + BugfixStr 33 | 34 | today = datetime.date.today() 35 | CFBundleGetInfoString = FullVersionStr + ", Copyright DevinMooers, " + str(today.year) 36 | CFBundleVersion = FullVersionStr 37 | 38 | print "update_version.py - setting version to " + FullVersionStr 39 | print "Updating plist version info..." 40 | 41 | plistpath = scriptpath + "/resources/Synthesis-VST2-Info.plist" 42 | vst2 = plistlib.readPlist(plistpath) 43 | vst2['CFBundleGetInfoString'] = CFBundleGetInfoString 44 | vst2['CFBundleVersion'] = CFBundleVersion 45 | vst2['CFBundleShortVersionString'] = CFBundleVersion 46 | plistlib.writePlist(vst2, plistpath) 47 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 48 | 49 | plistpath = scriptpath + "/resources/Synthesis-AU-Info.plist" 50 | au = plistlib.readPlist(plistpath) 51 | au['CFBundleGetInfoString'] = CFBundleGetInfoString 52 | au['CFBundleVersion'] = CFBundleVersion 53 | au['CFBundleShortVersionString'] = CFBundleVersion 54 | plistlib.writePlist(au, plistpath) 55 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 56 | 57 | plistpath = scriptpath + "/resources/Synthesis-VST3-Info.plist" 58 | vst3 = plistlib.readPlist(plistpath) 59 | vst3['CFBundleGetInfoString'] = CFBundleGetInfoString 60 | vst3['CFBundleVersion'] = CFBundleVersion 61 | vst3['CFBundleShortVersionString'] = CFBundleVersion 62 | plistlib.writePlist(vst3, plistpath) 63 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 64 | 65 | plistpath = scriptpath + "/resources/Synthesis-OSXAPP-Info.plist" 66 | app = plistlib.readPlist(plistpath) 67 | app['CFBundleGetInfoString'] = CFBundleGetInfoString 68 | app['CFBundleVersion'] = CFBundleVersion 69 | app['CFBundleShortVersionString'] = CFBundleVersion 70 | plistlib.writePlist(app, plistpath) 71 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 72 | 73 | plistpath = scriptpath + "/resources/Synthesis-RTAS-Info.plist" 74 | rtas = plistlib.readPlist(plistpath) 75 | rtas['CFBundleGetInfoString'] = CFBundleGetInfoString 76 | rtas['CFBundleVersion'] = CFBundleVersion 77 | rtas['CFBundleShortVersionString'] = CFBundleVersion 78 | plistlib.writePlist(rtas, plistpath) 79 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 80 | 81 | plistpath = scriptpath + "/resources/Synthesis-AAX-Info.plist" 82 | aax = plistlib.readPlist(plistpath) 83 | aax['CFBundleGetInfoString'] = CFBundleGetInfoString 84 | aax['CFBundleVersion'] = CFBundleVersion 85 | aax['CFBundleShortVersionString'] = CFBundleVersion 86 | plistlib.writePlist(aax, plistpath) 87 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 88 | 89 | # plistpath = scriptpath + "/resources/Synthesis-IOSAPP-Info.plist" 90 | # iosapp = plistlib.readPlist(plistpath) 91 | # iosapp['CFBundleGetInfoString'] = CFBundleGetInfoString 92 | # iosapp['CFBundleVersion'] = CFBundleVersion 93 | # iosapp['CFBundleShortVersionString'] = CFBundleVersion 94 | # plistlib.writePlist(iosapp, plistpath) 95 | # replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 96 | 97 | print "Updating Mac Installer version info..." 98 | 99 | plistpath = scriptpath + "/installer/Synthesis.pkgproj" 100 | installer = plistlib.readPlist(plistpath) 101 | 102 | for x in range(0,6): 103 | installer['PACKAGES'][x]['PACKAGE_SETTINGS']['VERSION'] = FullVersionStr 104 | 105 | plistlib.writePlist(installer, plistpath) 106 | replacestrs(plistpath, "//Apple//", "//Apple Computer//"); 107 | 108 | print "Updating Windows Installer version info..." 109 | 110 | for line in fileinput.input(scriptpath + "/installer/Synthesis.iss",inplace=1): 111 | if "AppVersion" in line: 112 | line="AppVersion=" + FullVersionStr + "\n" 113 | sys.stdout.write(line) 114 | 115 | if __name__ == '__main__': 116 | main() -------------------------------------------------------------------------------- /validate_audiounit.command: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # shell script to validate your iplug audiounit using auval 3 | # run from terminal with the argument leaks to perform the leaks test (See auval docs) 4 | 5 | BASEDIR=$(dirname $0) 6 | 7 | cd $BASEDIR 8 | 9 | PUID=`echo | grep PLUG_UNIQUE_ID resource.h` 10 | PUID=${PUID//\#define PLUG_UNIQUE_ID } 11 | PUID=${PUID//\'} 12 | 13 | PMID=`echo | grep PLUG_MFR_ID resource.h` 14 | PMID=${PMID//\#define PLUG_MFR_ID } 15 | PMID=${PMID//\'} 16 | 17 | PII=`echo | grep PLUG_IS_INST resource.h` 18 | PII=${PII//\#define PLUG_IS_INST } 19 | 20 | PDM=`echo | grep PLUG_DOES_MIDI resource.h` 21 | PDM=${PDM//\#define PLUG_DOES_MIDI } 22 | 23 | echo $PII 24 | echo $PDM 25 | 26 | TYPE=aufx 27 | 28 | if [ $PII == 1 ] # instrument 29 | then 30 | TYPE=aumu 31 | else 32 | if [ $PDM == 1 ] # midi effect 33 | then 34 | TYPE=aumf 35 | fi 36 | fi 37 | 38 | if [ "$1" == "leaks" ] 39 | then 40 | echo "testing for leaks (i386 32 bit)" 41 | echo 'launch a new shell and type: ps axc|awk "{if (\$5==\"auvaltool\") print \$1}" to get the pid'; 42 | echo "then leaks PID" 43 | 44 | export MallocStackLogging=1 45 | set env MallocStackLoggingNoCompact=1 46 | 47 | auval -v $TYPE $PUID $PMID -w -q 48 | 49 | unset MallocStackLogging 50 | 51 | else 52 | 53 | echo "\nvalidating i386 32 bit... ------------------------" 54 | echo "--------------------------------------------------" 55 | echo "--------------------------------------------------" 56 | echo "--------------------------------------------------" 57 | echo "--------------------------------------------------" 58 | echo "--------------------------------------------------" 59 | 60 | auval -v $TYPE $PUID $PMID 61 | 62 | echo "\nvalidating i386 64 bit... ------------------------" 63 | echo "--------------------------------------------------" 64 | echo "--------------------------------------------------" 65 | echo "--------------------------------------------------" 66 | echo "--------------------------------------------------" 67 | echo "--------------------------------------------------" 68 | 69 | auval -64 -v $TYPE $PUID $PMID 70 | 71 | #[ -e "/var/db/receipts/com.apple.pkg.Rosetta.plist" ] && echo Rosetta installed || echo Rosetta NOT installed 72 | #ppc auval not available on 10.6 73 | 74 | #echo "\nvalidating ppc 32 bit... -------------------------" 75 | #echo "--------------------------------------------------" 76 | #echo "--------------------------------------------------" 77 | #echo "--------------------------------------------------" 78 | #echo "--------------------------------------------------" 79 | #echo "--------------------------------------------------" 80 | 81 | #auval -ppc -v $TYPE $PUID $PMID 82 | fi 83 | 84 | echo "done" 85 | 86 | --------------------------------------------------------------------------------