1 #pragma once
2 #include "StringOsc.h"
3 #include "StringFilters.h"
4 #include "SolinaChorus.h"
5 #include "dsp/ADSREnvelope.h"
6 #include "dsp/TriangleLFO.h"
7 #include <boost/intrusive/list.hpp>
8 #include <memory>
9 #include <cstdint>
10 
11 class StringSynth {
12 public:
13     StringSynth();
14     ~StringSynth();
15 
16     void init(double sampleRate);
17 
18     void handleMessage(const uint8_t *msg);
19     void resetAllControllers();
20     void generate(float *outputs[2], unsigned count);
21 
getDetune()22     float getDetune() const { return fDetuneAmount; }
setDetune(float amount)23     void setDetune(float amount) { fDetuneAmount = amount; }
24 
getOscSettings()25     const StringOsc::Settings &getOscSettings() const { return fOscSettings; }
getOscSettings()26     StringOsc::Settings &getOscSettings() { return fOscSettings; }
27 
getEnvSettings()28     const ADSREnvelope::Settings &getEnvSettings() const { return fEnvSettings; }
getEnvSettings()29     ADSREnvelope::Settings &getEnvSettings() { return fEnvSettings; }
30 
getFltSettings()31     const StringFilters::Settings &getFltSettings() const { return fFltSettings; }
getFltSettings()32     StringFilters::Settings &getFltSettings() { return fFltSettings; }
33 
getMixGainUpper()34     float getMixGainUpper() const { return fMixGainUpper; }
setMixGainUpper(float value)35     void setMixGainUpper(float value) { fMixGainUpper = value; }
getMixGainLower()36     float getMixGainLower() const { return fMixGainLower; }
setMixGainLower(float value)37     void setMixGainLower(float value) { fMixGainLower = value; }
38 
getChorus()39     const SolinaChorus &getChorus() const { return fChorus; }
getChorus()40     SolinaChorus &getChorus() { return fChorus; }
41 
getMasterGain()42     float getMasterGain() const { return fMasterGain; }
setMasterGain(float value)43     void setMasterGain(float value) { fMasterGain = value; }
44 
getLastDetuneUpper()45     float getLastDetuneUpper() const { return fLastDetuneUpper; }
getLastDetuneLower()46     float getLastDetuneLower() const { return fLastDetuneLower; }
47 
48 private:
49     struct Voice : boost::intrusive::list_base_hook<> {
50         unsigned note;
51         float pitch;
52         float bend;
53         bool active;
54         ADSREnvelope env;
55         StringOsc osc;
56         StringFilters flt;
57     };
58 
59 private:
60     std::unique_ptr<Voice[]> fVoices;
61     boost::intrusive::list<Voice> fActiveVoices;
62 
63     float fDetuneAmount;
64     TriangleLFO fDetuneLFO[2];
65 
66     float fLastDetuneUpper;
67     float fLastDetuneLower;
68 
69     float fMixGainUpper;
70     float fMixGainLower;
71 
72     StringOsc::Settings fOscSettings;
73     ADSREnvelope::Settings fEnvSettings;
74     StringFilters::Settings fFltSettings;
75 
76     SolinaChorus fChorus;
77 
78     float fMasterGain;
79 
80     float fCtlPitchBend;
81     float fCtlPitchBendSensitivity;
82 
83     struct RpnIdentifier {
84         unsigned registered : 1;
85         unsigned msb : 7;
86         unsigned lsb : 7;
87     };
88     RpnIdentifier fCtlRpnIdentifier;
89 
90 private:
91     void noteOn(unsigned note, unsigned vel);
92     void noteOff(unsigned note, unsigned vel);
93     void allNotesOff();
94     void allSoundOff();
95     bool generateVoiceAdding(Voice &voice, float *output, const float *const detune[2], float bend, unsigned count);
96     static void clearFinishedVoice(Voice &voice);
97     static bool voiceHasReleased(const Voice &voice);
98     static bool voiceHasFinished(const Voice &voice);
99 };
100