arduino-audio-tools
Loading...
Searching...
No Matches
Synthesizer.h
Go to the documentation of this file.
1#pragma once
2
8#include "SoundGenerator.h"
9#include "AudioEffects.h"
10#ifdef USE_MIDI
11#include "Midi.h"
12#endif
13
14namespace audio_tools {
15
23 public:
24 virtual ~AbstractSynthesizerChannel() = default;
27 virtual void begin(AudioInfo config);
29 virtual bool isActive() = 0;
31 virtual void keyOn(int nte, float tgt) = 0;
33 virtual void keyOff() = 0;
35 virtual int16_t readSample()=0;
37 virtual int note() = 0 ;
38};
39
48 public:
51
55
58
60 TRACED();
61 auto result = new DefaultSynthesizerChannel(*this);
62 result->begin(config);
63 return result;
64 }
65
67 p_generator = &generator;
68 }
69
70 virtual void begin(AudioInfo config) override {
71 TRACEI();
72 this->config = config;
74
75 // setup generator
76 if (p_generator==nullptr){
78 p_generator = &sine;
79 }
81
82 // find ADSRGain
84 if (p_adsr==nullptr){
85 p_adsr = new ADSRGain(0.0001, 0.0001, 0.8, 0.0005);
86 p_adsr->setId(1);
88 }
89 }
90
91 virtual bool isActive() override{
92 return p_adsr != nullptr ? p_adsr->isActive() : false;
93 }
94
96 virtual void keyOn(int note, float tgt) override{
97 if (p_generator!=nullptr){
99 }
100 if (p_adsr!=nullptr){
102 p_adsr->keyOn(tgt);
103 }
104 }
105
106 virtual void keyOff() override{
107 TRACED();
108 if (p_adsr!=nullptr){
109 p_adsr->keyOff();
110 } else {
111 LOGE("p_adsr is null")
112 }
113 }
114
115 virtual int16_t readSample() override{
116 if (p_generator==nullptr) return 0;
117 int16_t sample = p_generator->readSample();
118 int size = effects.size();
119 for (int j=0; j<size; j++){
120 sample = effects[j]->process(sample);
121 }
122 return sample;
123 }
124
125 virtual int note() override {
126 return actual_note;
127 }
128
130 effects.addEffect(ptr);
131 }
132
133 protected:
137 ADSRGain *p_adsr = nullptr;
138 int actual_note = 0;
139
140};
141
142
150 int pin;
151 float note;
152};
153
161class Synthesizer : public SoundGenerator<int16_t> {
162 public:
166
170
171 Synthesizer(Synthesizer const&) = delete;
173
174 virtual ~Synthesizer(){
175 TRACED();
176 for (int j=0;j<channels.size();j++){
177 delete channels[j];
178 channels[j] = nullptr;
179 }
180
181#ifdef USE_MIDI
182 delete p_synth_action;
183#endif
184 }
185
186 bool begin(AudioInfo config) {
187 TRACEI();
188 this->cfg = config;
190 // provide config to defaut
191 defaultChannel->begin(config);
192 return true;
193 }
194
195 void keyOn(int note, float tgt=0){
196 LOGI("keyOn: %d", note);
198 if (channel!=nullptr){
199 channel->keyOn(note, tgt);
200 } else {
201 LOGW("No channel available for %d",note);
202 }
203 }
204
205 void keyOff(int note){
206 LOGI("keyOff: %d", note);
208 if (channel!=nullptr){
209 channel->keyOff();
210 }
211 }
212
214 int16_t readSample() override {
215 int total = 0;
216 uint16_t count = 0;
217 // calculate sum of all channels
218 for (int j=0;j<channels.size();j++){
219 if (channels[j]->isActive()){
220 count++;
221 total += channels[j]->readSample();
222 }
223 }
224 // prevent divide by zero
225 int result = 0;
226 if (count>0){
227 result = NumberConverter::clipT<int16_t>(total / count);
228 }
229 return result;
230 }
231
234 while (p_keys->note > 0){
235 actions.add(p_keys->pin, callbackKeyOn, callbackKeyOff, activeValue , new KeyParameter(this, p_keys->note));
236 p_keys++;
237 }
238 }
239
241 void setMidiName(const char* name){
242 midi_name = name;
243 }
244
245 protected:
249 const char* midi_name = "Synthesizer";
250
259
260#ifdef USE_MIDI
261
263 class SynthAction : public MidiAction {
264 private:
265 Synthesizer *synth=nullptr;
266 public:
267 SynthAction(Synthesizer *synth){
268 this->synth = synth;
269 }
270 void onNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
271 int frq = MidiCommon::noteToFrequency(note);
272 float vel = 1.0/127.0 * velocity;
273 synth->keyOn(frq, vel);
274 }
275 void onNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) {
276 int frq = MidiCommon::noteToFrequency(note);
277 synth->keyOff(frq);
278 }
279 void onControlChange(uint8_t channel, uint8_t controller, uint8_t value) {}
280 void onPitchBend(uint8_t channel, uint8_t value) {}
281 };
282
284 // Midi BLE Server
286
287#endif
288
289 // gets the channel for the indicated note
291 LOGI("getNoteChannel: %d", note);
292 for (int j=0;j<channels.size();j++){
293 if (channels[j]->note() == note){
294 return channels[j];
295 }
296 }
297 return nullptr;
298 }
299
300 // gets a free channel
302 LOGI("getFreeChannel");
303 for (int j=0;j<channels.size();j++){
304 if (!channels[j]->isActive()){
305 return channels[j];
306 }
307 }
308 LOGI("No free channel found: Adding new channel");
310 channels.push_back(ch);
311 return ch;
312 }
313
314 static void callbackKeyOn(bool active, int pin, void* ref){
315 TRACEI();
317 if (par !=nullptr && par->p_synthesizer!=nullptr){
318 par->p_synthesizer->keyOn(par->note);
319 } else {
320 LOGE("callbackKeyOn: unexpected null")
321 }
322 }
323
324 static void callbackKeyOff(bool active, int pin, void* ref){
325 TRACEI();
327 if (par !=nullptr){
328 if (par->p_synthesizer!=nullptr){
329 par->p_synthesizer->keyOff(par->note);
330 } else {
331 LOGE("callbackKeyOff: p_synthesizer is null");
332 }
333 } else {
334 LOGE("callbackKeyOff: ref is null");
335 }
336 }
337};
338
339} // namespace
340
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
ADSR Envelope: Attack, Decay, Sustain and Release. Attack is the time taken for initial run-up oeffec...
Definition AudioEffect.h:354
void keyOn(float tgt=0)
Definition AudioEffect.h:386
bool isActive()
Definition AudioEffect.h:396
void keyOff()
Definition AudioEffect.h:388
Defines the sound generation for one channel. A channel is used to process an indivudual key so that ...
Definition Synthesizer.h:22
virtual void keyOff()=0
Provides the key off event to ADSR to stop the sound.
virtual AbstractSynthesizerChannel * clone()=0
virtual void begin(AudioInfo config)
Start the sound generation.
virtual bool isActive()=0
Checks if the ADSR is still active - and generating sound.
virtual int16_t readSample()=0
Provides the next sample.
virtual int note()=0
Provides the actual midi note that is played.
virtual void keyOn(int nte, float tgt)=0
Provides the key on event to ADSR to start the sound.
A simple class to assign functions to gpio pins e.g. to implement a simple navigation control or volu...
Definition AudioActions.h:29
ActiveLogic
Definition AudioActions.h:31
void add(Action &action)
Adds an Action.
Definition AudioActions.h:139
Definition AudioEffects.h:24
size_t size()
Provides the actual number of defined effects.
Definition AudioEffects.h:45
AudioEffect * findEffect(int id)
Finds an effect by id.
Definition AudioEffects.h:50
void addEffect(AudioEffect &effect)
Adds an effect object (by reference)
Definition AudioEffects.h:27
Abstract Base class for Sound Effects.
Definition AudioEffect.h:23
void setId(int id)
Allows to identify an effect.
Definition AudioEffect.h:43
Default implementation for a Channel. You can provide the Sound Generator as parameter to the effects...
Definition Synthesizer.h:47
AudioInfo config
Definition Synthesizer.h:134
int actual_note
Definition Synthesizer.h:138
DefaultSynthesizerChannel()=default
Default constructor.
virtual void keyOn(int note, float tgt) override
start to play a note - note expects the frequency of the note!
Definition Synthesizer.h:96
virtual void keyOff() override
Provides the key off event to ADSR to stop the sound.
Definition Synthesizer.h:106
virtual void begin(AudioInfo config) override
Start the sound generation.
Definition Synthesizer.h:70
virtual int note() override
Provides the actual midi note that is played.
Definition Synthesizer.h:125
ADSRGain * p_adsr
Definition Synthesizer.h:137
SoundGenerator< int16_t > * p_generator
Definition Synthesizer.h:136
virtual int16_t readSample() override
Provides the next sample.
Definition Synthesizer.h:115
void setGenerator(SoundGenerator< int16_t > &generator)
Definition Synthesizer.h:66
void addEffect(AudioEffect *ptr)
Definition Synthesizer.h:129
virtual bool isActive() override
Checks if the ADSR is still active - and generating sound.
Definition Synthesizer.h:91
AudioEffectCommon effects
Definition Synthesizer.h:135
DefaultSynthesizerChannel(SoundGenerator< int16_t > &generator)
Definition Synthesizer.h:52
DefaultSynthesizerChannel(DefaultSynthesizerChannel &ch)=default
Copy constructor.
DefaultSynthesizerChannel * clone() override
Definition Synthesizer.h:59
Sine wave which is based on a fast approximation function.
Definition SoundGenerator.h:320
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:28
bool active
Definition SoundGenerator.h:111
virtual T readSample()=0
Provides a single sample.
virtual bool begin(AudioInfo info)
Definition SoundGenerator.h:34
virtual void setFrequency(float frequency)
Abstract method: not implemented! Just provides an error message...
Definition SoundGenerator.h:82
virtual bool begin()
Definition SoundGenerator.h:39
virtual bool isActive()
Definition SoundGenerator.h:56
A simple Synthesizer which can generate sound having multiple keys pressed. The main purpose of this ...
Definition Synthesizer.h:161
const char * midi_name
Definition Synthesizer.h:249
AbstractSynthesizerChannel * getFreeChannel()
Definition Synthesizer.h:301
AudioInfo cfg
Definition Synthesizer.h:246
void keyOn(int note, float tgt=0)
Definition Synthesizer.h:195
Synthesizer(AbstractSynthesizerChannel *ch)
Definition Synthesizer.h:167
int16_t readSample() override
Provides mixed samples of all channels.
Definition Synthesizer.h:214
AbstractSynthesizerChannel * getNoteChannel(int note)
Definition Synthesizer.h:290
Synthesizer()
Definition Synthesizer.h:163
void setKeys(AudioActions &actions, SynthesizerKey *p_keys, AudioActions::ActiveLogic activeValue)
Assigns pins to notes - the last SynthesizerKey is marked with an entry containing the note <= 0.
Definition Synthesizer.h:233
Synthesizer & operator=(Synthesizer const &)=delete
void keyOff(int note)
Definition Synthesizer.h:205
AbstractSynthesizerChannel * defaultChannel
Definition Synthesizer.h:247
static void callbackKeyOff(bool active, int pin, void *ref)
Definition Synthesizer.h:324
void setMidiName(const char *name)
Defines the midi name.
Definition Synthesizer.h:241
Vector< AbstractSynthesizerChannel * > channels
Definition Synthesizer.h:248
virtual ~Synthesizer()
Definition Synthesizer.h:174
static void callbackKeyOn(bool active, int pin, void *ref)
Definition Synthesizer.h:314
bool begin(AudioInfo config)
Definition Synthesizer.h:186
Synthesizer(Synthesizer const &)=delete
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
virtual void logInfo(const char *source="")
Definition AudioTypes.h:125
Definition Synthesizer.h:251
KeyParameter(Synthesizer *synth, int nte)
Definition Synthesizer.h:252
int note
Definition Synthesizer.h:257
Synthesizer * p_synthesizer
Definition Synthesizer.h:256
Arduino GPIO pin to note assossiation.
Definition Synthesizer.h:149
float note
Definition Synthesizer.h:151
int pin
Definition Synthesizer.h:150