@@ -22,7 +22,7 @@ class AbstractSynth : public Synth, public MidiProcessor, public VelocityCurve {
2222 /* *
2323 * Set note in whole semitones and update frequency
2424 */
25- void setNote (uint8_t note){
25+ virtual void setNote (uint8_t note){
2626 this ->note = note;
2727 setFrequency (noteToFrequency (note+pb));
2828 }
@@ -35,7 +35,7 @@ class AbstractSynth : public Synth, public MidiProcessor, public VelocityCurve {
3535 /* *
3636 * Set pitch bend amount in semitones and update frequency
3737 */
38- void setPitchBend (float pb){
38+ virtual void setPitchBend (float pb){
3939 this ->pb = pb;
4040 setFrequency (noteToFrequency (note+pb));
4141 }
@@ -53,25 +53,35 @@ class AbstractSynth : public Synth, public MidiProcessor, public VelocityCurve {
5353 this ->pb_range = range;
5454 }
5555 // MIDI handlers
56- virtual void noteOn (MidiMessage msg){
56+ virtual void noteOn (MidiMessage msg) override {
5757 setNote (msg.getNote ());
5858 setFrequency (noteToFrequency (note+pb));
5959 setGain (velocityToGain (msg.getVelocity ()));
6060 gate (true );
6161 }
62- virtual void noteOff (MidiMessage msg){
62+ virtual void noteOff (MidiMessage msg) override {
6363 gate (false );
6464 }
65- virtual void controlChange (MidiMessage msg){
66- if (msg.getControllerNumber () == MIDI_ALL_NOTES_OFF)
65+ virtual void controlChange (MidiMessage msg) override {
66+ if (msg.getControllerNumber () == MIDI_CC_MODULATION)
67+ setModulation (msg.getControllerValue ()/127 .0f );
68+ else if (msg.getControllerNumber () == MIDI_ALL_NOTES_OFF)
6769 allNotesOff ();
6870 }
69- virtual void allNotesOff (){
70- gate (false );
71+ virtual void channelPressure (MidiMessage msg) override {
72+ setPressure (msg.getChannelPressure ()/127 .0f );
73+ }
74+ virtual void polyKeyPressure (MidiMessage msg) override {
75+ setPressure (msg.getPolyKeyPressure ()/127 .0f );
7176 }
72- virtual void pitchbend (MidiMessage msg){
77+ virtual void setModulation (float modulation){} // default implementation does nothing
78+ virtual void setPressure (float pressure){}
79+ virtual void pitchbend (MidiMessage msg) override {
7380 setPitchBend (pb_range*msg.getPitchBend ()/8192 .0f );
7481 }
82+ virtual void allNotesOff (){
83+ gate (false );
84+ }
7585 // static utility methods
7686 static inline float frequencyToNote (float freq){
7787 return 12 * log2f (freq / 440 ) + 69 ;
@@ -80,154 +90,5 @@ class AbstractSynth : public Synth, public MidiProcessor, public VelocityCurve {
8090 return 440 * exp2f ((note - 69 ) / 12 );
8191 }
8292};
83-
84- template <class SynthVoice , int VOICES>
85- class PolyphonicProcessor : public MidiProcessor {
86- private:
87- static const uint16_t TAKEN = 0xffff ;
88- SynthVoice* voice[VOICES];
89- uint8_t notes[VOICES];
90- uint16_t allocation[VOICES];
91- uint16_t allocated;
92- FloatArray buffer;
93- protected:
94- void take (uint8_t ch, MidiMessage msg){
95- release (ch);
96- notes[ch] = msg.getNote ();
97- allocation[ch] = TAKEN;
98- voice[ch]->noteOn (msg);
99- }
100- void release (uint8_t ch){
101- allocation[ch] = ++allocated;
102- voice[ch]->gate (false );
103- }
104- public:
105- PolyphonicProcessor (FloatArray buffer) : allocated(0 ), buffer(buffer) {}
106- virtual ~PolyphonicProcessor (){};
107- static PolyphonicProcessor<SynthVoice, VOICES>* create (size_t blocksize){
108- FloatArray buffer = FloatArray::create (blocksize);
109- return new PolyphonicProcessor<SynthVoice, VOICES>(buffer);
110- }
111- static void destroy (PolyphonicProcessor<SynthVoice, VOICES>* obj){
112- delete obj->buffer ;
113- delete obj;
114- }
115- void noteOn (MidiMessage msg){
116- uint8_t note = msg.getNote ();
117- uint16_t minval = USHRT_MAX;
118- uint8_t minidx = 0 ;
119- // take oldest free voice, to allow voices to ring out
120- for (int i=0 ; i<VOICES; ++i){
121- if (notes[i] == note){
122- minidx = i;
123- break ;
124- }
125- if (allocation[i] < minval){
126- minidx = i;
127- minval = allocation[i];
128- }
129- }
130- // take oldest voice
131- take (minidx, msg);
132- }
133- void noteOff (MidiMessage msg){
134- uint8_t note = msg.getNote ();
135- for (int i=0 ; i<VOICES; ++i)
136- if (notes[i] == note)
137- release (i);
138- }
139- float generate (){
140- float sample = 0 .0f ;
141- for (int i=0 ; i<VOICES; ++i)
142- sample += voice[i]->generate ();
143- return sample;
144- }
145- void generate (FloatArray output){
146- voice[0 ]->generate (output);
147- for (int i=1 ; i<VOICES; ++i){
148- voice[i]->generate (buffer);
149- output.add (buffer);
150- }
151- }
152- void controlChange (MidiMessage msg){
153- if (msg.getControllerNumber () == MIDI_ALL_NOTES_OFF)
154- allNotesOff ();
155- }
156- void pitchbend (MidiMessage msg){
157- for (int i=0 ; i<VOICES; ++i)
158- voice[i]->pitchbend (msg);
159- }
160- void allNotesOn () {
161- for (int i=0 ; i<VOICES; ++i)
162- voice[i]->gate (true );
163- }
164- void allNotesOff () {
165- for (int i=0 ; i<VOICES; ++i)
166- voice[i]->gate (false );
167- }
168- void setVoice (size_t index, SynthVoice* obj){
169- if (index < VOICES)
170- voice[index] = obj;
171- }
172- SynthVoice* getVoice (size_t index){
173- if (index < VOICES)
174- return voice[index];
175- return NULL ;
176- }
177- };
178-
179- template <class SynthVoice >
180- class MonophonicProcessor : public MidiProcessor {
181- private:
182- SynthVoice* voice;
183- uint8_t notes[16 ];
184- uint8_t lastNote = 0 ;
185- public:
186- MonophonicProcessor (SynthVoice* voice) : voice(voice) {}
187- virtual void noteOn (MidiMessage msg){
188- if (lastNote < 16 )
189- notes[lastNote++] = msg.getNote ();
190- voice->noteOn (msg);
191- }
192- virtual void noteOff (MidiMessage msg){
193- uint8_t note = msg.getNote ();
194- int i;
195- for (i = 0 ; i < lastNote; ++i) {
196- if (notes[i] == note)
197- break ;
198- }
199- if (lastNote > 1 ) {
200- lastNote--;
201- while (i < lastNote) {
202- notes[i] = notes[i + 1 ];
203- i++;
204- }
205- voice->setNote (notes[lastNote - 1 ]);
206- }else {
207- voice->gate (false );
208- lastNote = 0 ;
209- }
210- }
211- void allNotesOff () {
212- voice->gate (false );
213- lastNote = 0 ;
214- }
215- float generate (){
216- return voice->generate ();
217- }
218- void generate (FloatArray output){
219- voice->generate (output);
220- }
221- void controlChange (MidiMessage msg){
222- if (msg.getControllerNumber () == MIDI_ALL_NOTES_OFF)
223- allNotesOff ();
224- }
225- void pitchbend (MidiMessage msg){
226- voice->pitchbend (msg);
227- }
228- SynthVoice* getVoice (){
229- return voice;
230- }
231- };
23293
23394#endif // __AbstractSynth_h__
0 commit comments