You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

939 lines
21KB

  1. /*
  2. ==============================================================================
  3. This file was auto-generated!
  4. It contains the basic startup code for a Juce application.
  5. ==============================================================================
  6. */
  7. #include "PluginProcessor.h"
  8. #include "PluginEditor.h"
  9. #include "Engine/Params.h"
  10. //==============================================================================
  11. #define S(T) (juce::String(T))
  12. //==============================================================================
  13. ObxdAudioProcessor::ObxdAudioProcessor()
  14. : programs()
  15. , configLock("__" JucePlugin_Name "ConfigLock__")
  16. {
  17. isHostAutomatedChange = true;
  18. synth.setSampleRate(44100);
  19. PropertiesFile::Options options;
  20. options.applicationName = JucePlugin_Name;
  21. options.storageFormat = PropertiesFile::storeAsXML;
  22. options.millisecondsBeforeSaving = 2500;
  23. options.processLock = &configLock;
  24. config = new PropertiesFile(getDocumentFolder().getChildFile("Settings.xml"), options);
  25. currentSkin = config->containsKey("skin") ? config->getValue("skin") : "discoDSP Grey";
  26. currentBank = "Init";
  27. scanAndUpdateBanks();
  28. initAllParams();
  29. if (bankFiles.size() > 0)
  30. {
  31. loadFromFXBFile(bankFiles[0]);
  32. }
  33. }
  34. ObxdAudioProcessor::~ObxdAudioProcessor()
  35. {
  36. config->saveIfNeeded();
  37. config = nullptr;
  38. }
  39. //==============================================================================
  40. void ObxdAudioProcessor::initAllParams()
  41. {
  42. for (int i = 0 ; i < PARAM_COUNT; i++)
  43. {
  44. setParameter(i, programs.currentProgramPtr->values[i]);
  45. }
  46. }
  47. //==============================================================================
  48. int ObxdAudioProcessor::getNumParameters()
  49. {
  50. return PARAM_COUNT;
  51. }
  52. float ObxdAudioProcessor::getParameter (int index)
  53. {
  54. return programs.currentProgramPtr->values[index];
  55. }
  56. void ObxdAudioProcessor::setParameter (int index, float newValue)
  57. {
  58. programs.currentProgramPtr->values[index] = newValue;
  59. switch(index)
  60. {
  61. case SELF_OSC_PUSH:
  62. synth.processSelfOscPush(newValue);
  63. break;
  64. case PW_ENV_BOTH:
  65. synth.processPwEnvBoth(newValue);
  66. break;
  67. case PW_OSC2_OFS:
  68. synth.processPwOfs(newValue);
  69. break;
  70. case ENV_PITCH_BOTH:
  71. synth.processPitchModBoth(newValue);
  72. break;
  73. case FENV_INVERT:
  74. synth.processInvertFenv(newValue);
  75. break;
  76. case LEVEL_DIF:
  77. synth.processLoudnessDetune(newValue);
  78. break;
  79. case PW_ENV:
  80. synth.processPwEnv(newValue);
  81. break;
  82. case LFO_SYNC:
  83. synth.procLfoSync(newValue);
  84. break;
  85. case ECONOMY_MODE:
  86. synth.procEconomyMode(newValue);
  87. break;
  88. case VAMPENV:
  89. synth.procAmpVelocityAmount(newValue);
  90. break;
  91. case VFLTENV:
  92. synth.procFltVelocityAmount(newValue);
  93. break;
  94. case ASPLAYEDALLOCATION:
  95. synth.procAsPlayedAlloc(newValue);
  96. break;
  97. case BENDLFORATE:
  98. synth.procModWheelFrequency(newValue);
  99. break;
  100. case FOURPOLE:
  101. synth.processFourPole(newValue);
  102. break;
  103. case LEGATOMODE:
  104. synth.processLegatoMode(newValue);
  105. break;
  106. case ENVPITCH:
  107. synth.processEnvelopeToPitch(newValue);
  108. break;
  109. case OSCQuantize:
  110. synth.processPitchQuantization(newValue);
  111. break;
  112. case VOICE_COUNT:
  113. synth.setVoiceCount(newValue);
  114. break;
  115. case BANDPASS:
  116. synth.processBandpassSw(newValue);
  117. break;
  118. case FILTER_WARM:
  119. synth.processOversampling(newValue);
  120. break;
  121. case BENDOSC2:
  122. synth.procPitchWheelOsc2Only(newValue);
  123. break;
  124. case BENDRANGE:
  125. synth.procPitchWheelAmount(newValue);
  126. break;
  127. case NOISEMIX:
  128. synth.processNoiseMix(newValue);
  129. break;
  130. case OCTAVE:
  131. synth.processOctave(newValue);
  132. break;
  133. case TUNE:
  134. synth.processTune(newValue);
  135. break;
  136. case BRIGHTNESS:
  137. synth.processBrightness(newValue);
  138. break;
  139. case MULTIMODE:
  140. synth.processMultimode(newValue);
  141. break;
  142. case LFOFREQ:
  143. synth.processLfoFrequency(newValue);
  144. break;
  145. case LFO1AMT:
  146. synth.processLfoAmt1(newValue);
  147. break;
  148. case LFO2AMT:
  149. synth.processLfoAmt2(newValue);
  150. break;
  151. case LFOSINWAVE:
  152. synth.processLfoSine(newValue);
  153. break;
  154. case LFOSQUAREWAVE:
  155. synth.processLfoSquare(newValue);
  156. break;
  157. case LFOSHWAVE:
  158. synth.processLfoSH(newValue);
  159. break;
  160. case LFOFILTER:
  161. synth.processLfoFilter(newValue);
  162. break;
  163. case LFOOSC1:
  164. synth.processLfoOsc1(newValue);
  165. break;
  166. case LFOOSC2:
  167. synth.processLfoOsc2(newValue);
  168. break;
  169. case LFOPW1:
  170. synth.processLfoPw1(newValue);
  171. break;
  172. case LFOPW2:
  173. synth.processLfoPw2(newValue);
  174. break;
  175. case PORTADER:
  176. synth.processPortamentoDetune(newValue);
  177. break;
  178. case FILTERDER:
  179. synth.processFilterDetune(newValue);
  180. break;
  181. case ENVDER:
  182. synth.processEnvelopeDetune(newValue);
  183. break;
  184. case XMOD:
  185. synth.processOsc2Xmod(newValue);
  186. break;
  187. case OSC2HS:
  188. synth.processOsc2HardSync(newValue);
  189. break;
  190. case OSC2P:
  191. synth.processOsc2Pitch(newValue);
  192. break;
  193. case OSC1P:
  194. synth.processOsc1Pitch(newValue);
  195. break;
  196. case PORTAMENTO:
  197. synth.processPortamento(newValue);
  198. break;
  199. case UNISON:
  200. synth.processUnison(newValue);
  201. break;
  202. case FLT_KF:
  203. synth.processFilterKeyFollow(newValue);
  204. break;
  205. case OSC1MIX:
  206. synth.processOsc1Mix(newValue);
  207. break;
  208. case OSC2MIX:
  209. synth.processOsc2Mix(newValue);
  210. break;
  211. case PW:
  212. synth.processPulseWidth(newValue);
  213. break;
  214. case OSC1Saw:
  215. synth.processOsc1Saw(newValue);
  216. break;
  217. case OSC2Saw:
  218. synth.processOsc2Saw(newValue);
  219. break;
  220. case OSC1Pul:
  221. synth.processOsc1Pulse(newValue);
  222. break;
  223. case OSC2Pul:
  224. synth.processOsc2Pulse(newValue);
  225. break;
  226. case VOLUME:
  227. synth.processVolume(newValue);
  228. break;
  229. case UDET:
  230. synth.processDetune(newValue);
  231. break;
  232. case OSC2_DET:
  233. synth.processOsc2Det(newValue);
  234. break;
  235. case CUTOFF:
  236. synth.processCutoff(newValue);
  237. break;
  238. case RESONANCE:
  239. synth.processResonance(newValue);
  240. break;
  241. case ENVELOPE_AMT:
  242. synth.processFilterEnvelopeAmt(newValue);
  243. break;
  244. case LATK:
  245. synth.processLoudnessEnvelopeAttack(newValue);
  246. break;
  247. case LDEC:
  248. synth.processLoudnessEnvelopeDecay(newValue);
  249. break;
  250. case LSUS:
  251. synth.processLoudnessEnvelopeSustain(newValue);
  252. break;
  253. case LREL:
  254. synth.processLoudnessEnvelopeRelease(newValue);
  255. break;
  256. case FATK:
  257. synth.processFilterEnvelopeAttack(newValue);
  258. break;
  259. case FDEC:
  260. synth.processFilterEnvelopeDecay(newValue);
  261. break;
  262. case FSUS:
  263. synth.processFilterEnvelopeSustain(newValue);
  264. break;
  265. case FREL:
  266. synth.processFilterEnvelopeRelease(newValue);
  267. break;
  268. case PAN1:
  269. synth.processPan(newValue,1);
  270. break;
  271. case PAN2:
  272. synth.processPan(newValue,2);
  273. break;
  274. case PAN3:
  275. synth.processPan(newValue,3);
  276. break;
  277. case PAN4:
  278. synth.processPan(newValue,4);
  279. break;
  280. case PAN5:
  281. synth.processPan(newValue,5);
  282. break;
  283. case PAN6:
  284. synth.processPan(newValue,6);
  285. break;
  286. case PAN7:
  287. synth.processPan(newValue,7);
  288. break;
  289. case PAN8:
  290. synth.processPan(newValue,8);
  291. break;
  292. }
  293. //DIRTY HACK
  294. //This should be checked to avoid stalling on gui update
  295. //It is needed because some hosts do wierd stuff
  296. if(isHostAutomatedChange)
  297. sendChangeMessage();
  298. }
  299. const String ObxdAudioProcessor::getParameterName (int index)
  300. {
  301. switch(index)
  302. {
  303. case SELF_OSC_PUSH:
  304. return S("SelfOscPush");
  305. case ENV_PITCH_BOTH:
  306. return S("EnvPitchBoth");
  307. case FENV_INVERT:
  308. return S("FenvInvert");
  309. case PW_OSC2_OFS:
  310. return S("PwOfs");
  311. case LEVEL_DIF:
  312. return S("LevelDif");
  313. case PW_ENV_BOTH:
  314. return S("PwEnvBoth");
  315. case PW_ENV:
  316. return S("PwEnv");
  317. case LFO_SYNC:
  318. return S("LfoSync");
  319. case ECONOMY_MODE:
  320. return S("EconomyMode");
  321. case UNUSED_1:
  322. return S("Unused 1");
  323. case UNUSED_2:
  324. return S("Unused 2");
  325. case VAMPENV:
  326. return S("VAmpFactor");
  327. case VFLTENV:
  328. return S("VFltFactor");
  329. case ASPLAYEDALLOCATION:
  330. return S("AsPlayedAllocation");
  331. case BENDLFORATE:
  332. return S("VibratoRate");
  333. case FOURPOLE:
  334. return S("FourPole");
  335. case LEGATOMODE:
  336. return S("LegatoMode");
  337. case ENVPITCH:
  338. return S("EnvelopeToPitch");
  339. case OSCQuantize:
  340. return S("PitchQuant");
  341. case VOICE_COUNT:
  342. return S("VoiceCount");
  343. case BANDPASS:
  344. return S("BandpassBlend");
  345. case FILTER_WARM:
  346. return S("Filter_Warm");
  347. case BENDRANGE:
  348. return S("BendRange");
  349. case BENDOSC2:
  350. return S("BendOsc2Only");
  351. case OCTAVE:
  352. return S("Octave");
  353. case TUNE:
  354. return S("Tune");
  355. case BRIGHTNESS:
  356. return S("Brightness");
  357. case NOISEMIX:
  358. return S("NoiseMix");
  359. case OSC1MIX:
  360. return S("Osc1Mix");
  361. case OSC2MIX:
  362. return S("Osc2Mix");
  363. case MULTIMODE:
  364. return S("Multimode");
  365. case LFOSHWAVE:
  366. return S("LfoSampleHoldWave");
  367. case LFOSINWAVE:
  368. return S("LfoSineWave");
  369. case LFOSQUAREWAVE:
  370. return S("LfoSquareWave");
  371. case LFO1AMT:
  372. return S("LfoAmount1");
  373. case LFO2AMT:
  374. return S("LfoAmount2");
  375. case LFOFILTER:
  376. return S("LfoFilter");
  377. case LFOOSC1:
  378. return S("LfoOsc1");
  379. case LFOOSC2:
  380. return S("LfoOsc2");
  381. case LFOFREQ:
  382. return S("LfoFrequency");
  383. case LFOPW1:
  384. return S("LfoPw1");
  385. case LFOPW2:
  386. return S("LfoPw2");
  387. case PORTADER:
  388. return S("PortamentoDetune");
  389. case FILTERDER:
  390. return S("FilterDetune");
  391. case ENVDER:
  392. return S("EnvelopeDetune");
  393. case PAN1:
  394. return S("Pan1");
  395. case PAN2:
  396. return S("Pan2");
  397. case PAN3:
  398. return S("Pan3");
  399. case PAN4:
  400. return S("Pan4");
  401. case PAN5:
  402. return S("Pan5");
  403. case PAN6:
  404. return S("Pan6");
  405. case PAN7:
  406. return S("Pan7");
  407. case PAN8:
  408. return S("Pan8");
  409. case XMOD:
  410. return S("Xmod");
  411. case OSC2HS:
  412. return S("Osc2HardSync");
  413. case OSC1P:
  414. return S("Osc1Pitch");
  415. case OSC2P:
  416. return S("Osc2Pitch");
  417. case PORTAMENTO:
  418. return S("Portamento");
  419. case UNISON:
  420. return S("Unison");
  421. case FLT_KF:
  422. return S("FilterKeyFollow");
  423. case PW:
  424. return S("PulseWidth");
  425. case OSC2Saw:
  426. return S("Osc2Saw");
  427. case OSC1Saw:
  428. return S("Osc1Saw");
  429. case OSC1Pul:
  430. return S("Osc1Pulse");
  431. case OSC2Pul:
  432. return S("Osc2Pulse");
  433. case VOLUME:
  434. return S("Volume");
  435. case UDET:
  436. return S("VoiceDetune");
  437. case OSC2_DET:
  438. return S("Oscillator2detune");
  439. case CUTOFF:
  440. return S("Cutoff");
  441. case RESONANCE:
  442. return S("Resonance");
  443. case ENVELOPE_AMT:
  444. return S("FilterEnvAmount");
  445. case LATK:
  446. return S("Attack");
  447. case LDEC:
  448. return S("Decay");
  449. case LSUS:
  450. return S("Sustain");
  451. case LREL:
  452. return S("Release");
  453. case FATK:
  454. return S("FilterAttack");
  455. case FDEC:
  456. return S("FilterDecay");
  457. case FSUS:
  458. return S("FilterSustain");
  459. case FREL:
  460. return S("FilterRelease");
  461. }
  462. return String();
  463. }
  464. const String ObxdAudioProcessor::getParameterText (int index)
  465. {
  466. return String(programs.currentProgramPtr->values[index],2);
  467. }
  468. //==============================================================================
  469. const String ObxdAudioProcessor::getName() const
  470. {
  471. return JucePlugin_Name;
  472. }
  473. const String ObxdAudioProcessor::getInputChannelName (int channelIndex) const
  474. {
  475. return String (channelIndex + 1);
  476. }
  477. const String ObxdAudioProcessor::getOutputChannelName (int channelIndex) const
  478. {
  479. return String (channelIndex + 1);
  480. }
  481. bool ObxdAudioProcessor::isInputChannelStereoPair (int index) const
  482. {
  483. return true;
  484. }
  485. bool ObxdAudioProcessor::isOutputChannelStereoPair (int index) const
  486. {
  487. return true;
  488. }
  489. bool ObxdAudioProcessor::acceptsMidi() const
  490. {
  491. #if JucePlugin_WantsMidiInput
  492. return true;
  493. #else
  494. return false;
  495. #endif
  496. }
  497. bool ObxdAudioProcessor::producesMidi() const
  498. {
  499. #if JucePlugin_ProducesMidiOutput
  500. return true;
  501. #else
  502. return false;
  503. #endif
  504. }
  505. bool ObxdAudioProcessor::silenceInProducesSilenceOut() const
  506. {
  507. return false;
  508. }
  509. double ObxdAudioProcessor::getTailLengthSeconds() const
  510. {
  511. return 0.0;
  512. }
  513. //==============================================================================
  514. int ObxdAudioProcessor::getNumPrograms()
  515. {
  516. return PROGRAMCOUNT;
  517. }
  518. int ObxdAudioProcessor::getCurrentProgram()
  519. {
  520. return programs.currentProgram;
  521. }
  522. void ObxdAudioProcessor::setCurrentProgram (int index)
  523. {
  524. programs.currentProgram = index;
  525. programs.currentProgramPtr = programs.programs + programs.currentProgram;
  526. isHostAutomatedChange = false;
  527. for(int i = 0 ; i < PARAM_COUNT;i++)
  528. setParameter(i,programs.currentProgramPtr->values[i]);
  529. isHostAutomatedChange = true;
  530. sendChangeMessage();
  531. updateHostDisplay();
  532. }
  533. const String ObxdAudioProcessor::getProgramName (int index)
  534. {
  535. return programs.programs[index].name;
  536. }
  537. void ObxdAudioProcessor::changeProgramName (int index, const String& newName)
  538. {
  539. programs.programs[index].name = newName;
  540. }
  541. //==============================================================================
  542. void ObxdAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
  543. {
  544. // Use this method as the place to do any pre-playback
  545. // initialisation that you need..
  546. nextMidi = MidiMessage(0xF0);
  547. midiMsg = MidiMessage(0xF0);
  548. synth.setSampleRate(sampleRate);
  549. }
  550. void ObxdAudioProcessor::releaseResources()
  551. {
  552. }
  553. inline void ObxdAudioProcessor::processMidiPerSample(MidiBuffer::Iterator* iter,const int samplePos)
  554. {
  555. while (getNextEvent(iter, samplePos))
  556. {
  557. if(midiMsg.isNoteOn())
  558. {
  559. synth.procNoteOn(midiMsg.getNoteNumber(),midiMsg.getFloatVelocity());
  560. }
  561. if (midiMsg.isNoteOff())
  562. {
  563. synth.procNoteOff(midiMsg.getNoteNumber());
  564. }
  565. if(midiMsg.isPitchWheel())
  566. {
  567. // [0..16383] center = 8192;
  568. synth.procPitchWheel((midiMsg.getPitchWheelValue()-8192) / 8192.0);
  569. }
  570. if(midiMsg.isController() && midiMsg.getControllerNumber()==1)
  571. synth.procModWheel(midiMsg.getControllerValue() / 127.0);
  572. if(midiMsg.isSustainPedalOn())
  573. {
  574. synth.sustainOn();
  575. }
  576. if(midiMsg.isSustainPedalOff() || midiMsg.isAllNotesOff()||midiMsg.isAllSoundOff())
  577. {
  578. synth.sustainOff();
  579. }
  580. if(midiMsg.isAllNotesOff())
  581. {
  582. synth.allNotesOff();
  583. }
  584. if(midiMsg.isAllSoundOff())
  585. {
  586. synth.allSoundOff();
  587. }
  588. }
  589. }
  590. bool ObxdAudioProcessor::getNextEvent(MidiBuffer::Iterator* iter,const int samplePos)
  591. {
  592. if (hasMidiMessage && midiEventPos <= samplePos)
  593. {
  594. midiMsg = nextMidi;
  595. hasMidiMessage = iter->getNextEvent(nextMidi, midiEventPos);
  596. return true;
  597. }
  598. return false;
  599. }
  600. void ObxdAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
  601. {
  602. MidiBuffer::Iterator ppp(midiMessages);
  603. hasMidiMessage = ppp.getNextEvent(nextMidi,midiEventPos);
  604. int samplePos = 0;
  605. int numSamples = buffer.getNumSamples();
  606. float* channelData1 = buffer.getWritePointer(0);
  607. float* channelData2 = buffer.getWritePointer(1);
  608. AudioPlayHead::CurrentPositionInfo pos;
  609. if (getPlayHead() != 0 && getPlayHead()->getCurrentPosition (pos))
  610. {
  611. synth.setPlayHead(pos.bpm,pos.ppqPosition);
  612. }
  613. while (samplePos < numSamples)
  614. {
  615. processMidiPerSample(&ppp,samplePos);
  616. synth.processSample(channelData1+samplePos,channelData2+samplePos);
  617. samplePos++;
  618. }
  619. }
  620. //==============================================================================
  621. bool ObxdAudioProcessor::hasEditor() const
  622. {
  623. return true;
  624. }
  625. AudioProcessorEditor* ObxdAudioProcessor::createEditor()
  626. {
  627. return new ObxdAudioProcessorEditor (this);
  628. }
  629. //==============================================================================
  630. void ObxdAudioProcessor::getStateInformation (MemoryBlock& destData)
  631. {
  632. XmlElement xmlState = XmlElement("Datsounds");
  633. xmlState.setAttribute(S("currentProgram"), programs.currentProgram);
  634. XmlElement* xprogs = new XmlElement("programs");
  635. for (int i = 0; i < PROGRAMCOUNT; ++i)
  636. {
  637. XmlElement* xpr = new XmlElement("program");
  638. xpr->setAttribute(S("programName"), programs.programs[i].name);
  639. for (int k = 0; k < PARAM_COUNT; ++k)
  640. {
  641. xpr->setAttribute(String(k), programs.programs[i].values[k]);
  642. }
  643. xprogs->addChildElement(xpr);
  644. }
  645. xmlState.addChildElement(xprogs);
  646. copyXmlToBinary(xmlState,destData);
  647. }
  648. void ObxdAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
  649. {
  650. if (XmlElement* const xmlState = getXmlFromBinary(data,sizeInBytes))
  651. {
  652. XmlElement* xprogs = xmlState->getFirstChildElement();
  653. if (xprogs->hasTagName(S("programs")))
  654. {
  655. int i = 0;
  656. forEachXmlChildElement(*xprogs, e)
  657. {
  658. programs.programs[i].setDefaultValues();
  659. for (int k = 0; k < PARAM_COUNT; ++k)
  660. {
  661. programs.programs[i].values[k] = e->getDoubleAttribute(String(k), programs.programs[i].values[k]);
  662. }
  663. programs.programs[i].name = e->getStringAttribute(S("programName"), S("Default"));
  664. ++i;
  665. }
  666. }
  667. setCurrentProgram(xmlState->getIntAttribute(S("currentProgram"), 0));
  668. delete xmlState;
  669. }
  670. }
  671. void ObxdAudioProcessor::setCurrentProgramStateInformation(const void* data,int sizeInBytes)
  672. {
  673. if (XmlElement* const e = getXmlFromBinary(data, sizeInBytes))
  674. {
  675. programs.currentProgramPtr->setDefaultValues();
  676. for (int k = 0; k < PARAM_COUNT; ++k)
  677. {
  678. programs.currentProgramPtr->values[k] = e->getDoubleAttribute(String(k), programs.currentProgramPtr->values[k]);
  679. }
  680. programs.currentProgramPtr->name = e->getStringAttribute(S("programName"), S("Default"));
  681. setCurrentProgram(programs.currentProgram);
  682. delete e;
  683. }
  684. }
  685. void ObxdAudioProcessor::getCurrentProgramStateInformation(MemoryBlock& destData)
  686. {
  687. XmlElement xmlState = XmlElement("Datsounds");
  688. for (int k = 0; k < PARAM_COUNT; ++k)
  689. {
  690. xmlState.setAttribute(String(k), programs.currentProgramPtr->values[k]);
  691. }
  692. xmlState.setAttribute(S("programName"), programs.currentProgramPtr->name);
  693. copyXmlToBinary(xmlState, destData);
  694. }
  695. //==============================================================================
  696. bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile)
  697. {
  698. MemoryBlock mb;
  699. if (! fxbFile.loadFileAsData(mb))
  700. return false;
  701. const void* const data = mb.getData();
  702. const size_t dataSize = mb.getSize();
  703. if (dataSize < 28)
  704. return false;
  705. const fxSet* const set = (const fxSet*) data;
  706. if ((! compareMagic (set->chunkMagic, "CcnK")) || fxbSwap (set->version) > fxbVersionNum)
  707. return false;
  708. if (compareMagic (set->fxMagic, "FxBk"))
  709. {
  710. // bank of programs
  711. if (fxbSwap (set->numPrograms) >= 0)
  712. {
  713. const int oldProg = getCurrentProgram();
  714. const int numParams = fxbSwap (((const fxProgram*) (set->programs))->numParams);
  715. const int progLen = (int) sizeof (fxProgram) + (numParams - 1) * (int) sizeof (float);
  716. for (int i = 0; i < fxbSwap (set->numPrograms); ++i)
  717. {
  718. if (i != oldProg)
  719. {
  720. const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + i * progLen);
  721. if (((const char*) prog) - ((const char*) set) >= (ssize_t) dataSize)
  722. return false;
  723. if (fxbSwap (set->numPrograms) > 0)
  724. setCurrentProgram (i);
  725. if (! restoreProgramSettings (prog))
  726. return false;
  727. }
  728. }
  729. if (fxbSwap (set->numPrograms) > 0)
  730. setCurrentProgram (oldProg);
  731. const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + oldProg * progLen);
  732. if (((const char*) prog) - ((const char*) set) >= (ssize_t) dataSize)
  733. return false;
  734. if (! restoreProgramSettings (prog))
  735. return false;
  736. }
  737. }
  738. else if (compareMagic (set->fxMagic, "FxCk"))
  739. {
  740. // single program
  741. const fxProgram* const prog = (const fxProgram*) data;
  742. if (! compareMagic (prog->chunkMagic, "CcnK"))
  743. return false;
  744. changeProgramName (getCurrentProgram(), prog->prgName);
  745. for (int i = 0; i < fxbSwap (prog->numParams); ++i)
  746. setParameter (i, fxbSwapFloat (prog->params[i]));
  747. }
  748. else if (compareMagic (set->fxMagic, "FBCh"))
  749. {
  750. // non-preset chunk
  751. const fxChunkSet* const cset = (const fxChunkSet*) data;
  752. if ((size_t) fxbSwap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (size_t) dataSize)
  753. return false;
  754. setStateInformation(cset->chunk, fxbSwap (cset->chunkSize));
  755. }
  756. else if (compareMagic (set->fxMagic, "FPCh"))
  757. {
  758. // preset chunk
  759. const fxProgramSet* const cset = (const fxProgramSet*) data;
  760. if ((size_t) fxbSwap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (size_t) dataSize)
  761. return false;
  762. setCurrentProgramStateInformation(cset->chunk, fxbSwap (cset->chunkSize));
  763. changeProgramName (getCurrentProgram(), cset->name);
  764. }
  765. else
  766. {
  767. return false;
  768. }
  769. currentBank = fxbFile.getFileName();
  770. updateHostDisplay();
  771. return true;
  772. }
  773. bool ObxdAudioProcessor::restoreProgramSettings(const fxProgram* const prog)
  774. {
  775. if (compareMagic (prog->chunkMagic, "CcnK")
  776. && compareMagic (prog->fxMagic, "FxCk"))
  777. {
  778. changeProgramName (getCurrentProgram(), prog->prgName);
  779. for (int i = 0; i < fxbSwap (prog->numParams); ++i)
  780. setParameter (i, fxbSwapFloat (prog->params[i]));
  781. return true;
  782. }
  783. return false;
  784. }
  785. //==============================================================================
  786. void ObxdAudioProcessor::scanAndUpdateBanks()
  787. {
  788. bankFiles.clearQuick();
  789. DirectoryIterator it(getBanksFolder(), false, "*.fxb", File::findFiles);
  790. while (it.next())
  791. {
  792. bankFiles.add(it.getFile());
  793. }
  794. }
  795. const Array<File>& ObxdAudioProcessor::getBankFiles() const
  796. {
  797. return bankFiles;
  798. }
  799. File ObxdAudioProcessor::getCurrentBankFile() const
  800. {
  801. return getBanksFolder().getChildFile(currentBank);
  802. }
  803. //==============================================================================
  804. File ObxdAudioProcessor::getDocumentFolder() const
  805. {
  806. File folder = File::getSpecialLocation(File::userDocumentsDirectory).getChildFile("discoDSP").getChildFile("OB-Xd");
  807. if (folder.isSymbolicLink())
  808. folder = folder.getLinkedTarget();
  809. return folder;
  810. }
  811. File ObxdAudioProcessor::getSkinFolder() const
  812. {
  813. return getDocumentFolder().getChildFile("Skins");
  814. }
  815. File ObxdAudioProcessor::getBanksFolder() const
  816. {
  817. return getDocumentFolder().getChildFile("Banks");
  818. }
  819. File ObxdAudioProcessor::getCurrentSkinFolder() const
  820. {
  821. return getSkinFolder().getChildFile(currentSkin);
  822. }
  823. void ObxdAudioProcessor::setCurrentSkinFolder(const String& folderName)
  824. {
  825. currentSkin = folderName;
  826. config->setValue("skin", folderName);
  827. config->setNeedsToBeSaved(true);
  828. }
  829. //==============================================================================
  830. // This creates new instances of the plugin..
  831. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  832. {
  833. return new ObxdAudioProcessor();
  834. }