+ Equalizers: convert lists of per-band parameters using macros (ugly, but effective)
[calf.git] / src / synth.cpp
blob47fa95fde6d1cff0ec02b486eac362f00178db69
1 /* Calf DSP Library
2 * Generic polyphonic synthesizer framework.
4 * Copyright (C) 2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 #include <config.h>
22 #include <assert.h>
23 #include <memory.h>
24 #if USE_JACK
25 #include <jack/jack.h>
26 #endif
27 #include <calf/giface.h>
28 #include <calf/synth.h>
30 using namespace dsp;
31 using namespace std;
33 void basic_synth::kill_note(int note, int vel, bool just_one)
35 for (list<dsp::voice *>::iterator it = active_voices.begin(); it != active_voices.end(); it++) {
36 // preserve sostenuto notes
37 if ((*it)->get_current_note() == note && !(sostenuto && (*it)->sostenuto)) {
38 (*it)->note_off(vel);
39 if (just_one)
40 return;
45 dsp::voice *basic_synth::give_voice()
47 if (active_voices.size() >= polyphony_limit)
49 dsp::voice *stolen = steal_voice();
50 if (stolen)
51 return stolen;
53 if (unused_voices.empty())
54 return alloc_voice();
55 else {
56 dsp::voice *v = unused_voices.top();
57 unused_voices.pop();
58 v->reset();
59 return v;
63 dsp::voice *basic_synth::steal_voice()
65 std::list<dsp::voice *>::iterator found = active_voices.end();
66 float priority = 10000;
67 //int idx = 0;
68 for(std::list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
70 //printf("Voice %d priority %f at %p\n", idx++, (*i)->get_priority(), *i);
71 if ((*i)->get_priority() < priority)
73 priority = (*i)->get_priority();
74 found = i;
77 //printf("Found: %p\n\n", *found);
78 if (found == active_voices.end())
79 return NULL;
81 (*found)->steal();
82 return NULL;
85 void basic_synth::trim_voices()
87 // count stealable voices
88 unsigned int count = 0;
89 for(std::list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
91 if ((*i)->get_priority() < 10000)
92 count++;
94 // printf("Count=%d limit=%d\n", count, polyphony_limit);
95 // steal any voices above polyphony limit
96 if (count > polyphony_limit) {
97 for (unsigned int i = 0; i < count - polyphony_limit; i++)
98 steal_voice();
102 void basic_synth::note_on(int note, int vel)
104 if (!vel) {
105 note_off(note, 0);
106 return;
108 bool perc = check_percussion();
109 dsp::voice *v = give_voice();
110 v->setup(sample_rate);
111 v->released = false;
112 v->sostenuto = false;
113 gate.set(note);
114 v->note_on(note, vel);
115 active_voices.push_back(v);
116 if (perc) {
117 percussion_note_on(note, vel);
121 void basic_synth::note_off(int note, int vel)
123 gate.reset(note);
124 if (!hold)
125 kill_note(note, vel, false);
128 #define for_all_voices(iter) for (std::list<dsp::voice *>::iterator iter = active_voices.begin(); iter != active_voices.end(); iter++)
130 void basic_synth::on_pedal_release()
132 for_all_voices(i)
134 int note = (*i)->get_current_note();
135 if (note < 0 || note > 127)
136 continue;
137 bool still_held = gate[note];
138 // sostenuto pedal released
139 if ((*i)->sostenuto && !sostenuto)
141 // mark note as non-sostenuto
142 (*i)->sostenuto = false;
143 // if key still pressed or hold pedal used, hold the note (as non-sostenuto so it can be released later by releasing the key or pedal)
144 // if key has been released and hold pedal is not depressed, release the note
145 if (!still_held && !hold)
146 (*i)->note_off(127);
148 else if (!hold && !still_held && !(*i)->released)
150 (*i)->released = true;
151 (*i)->note_off(127);
156 void basic_synth::control_change(int ctl, int val)
158 if (ctl == 64) { // HOLD controller
159 bool prev = hold;
160 hold = (val >= 64);
161 if (!hold && prev && !sostenuto) {
162 on_pedal_release();
165 if (ctl == 66) { // SOSTENUTO controller
166 bool prev = sostenuto;
167 sostenuto = (val >= 64);
168 if (sostenuto && !prev) {
169 // SOSTENUTO was pressed - move all notes onto sustain stack
170 for_all_voices(i) {
171 (*i)->sostenuto = true;
174 if (!sostenuto && prev) {
175 // SOSTENUTO was released - release all keys which were previously held
176 on_pedal_release();
179 if (ctl == 123 || ctl == 120) { // all notes off, all sounds off
180 vector<int> notes;
181 notes.reserve(128);
182 if (ctl == 120) { // for "all sounds off", automatically release hold and sostenuto pedal
183 control_change(66, 0);
184 control_change(64, 0);
186 for_all_voices(i)
188 if (ctl == 123)
189 (*i)->note_off(127);
190 else
191 (*i)->steal();
194 if (ctl == 121) {
195 control_change(1, 0);
196 control_change(7, 100);
197 control_change(10, 64);
198 control_change(11, 127);
199 // release hold..hold2
200 for (int i = 64; i <= 69; i++)
201 control_change(i, 0);
205 void basic_synth::render_to(float (*output)[2], int nsamples)
207 // render voices, eliminate ones that aren't sounding anymore
208 for (list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end();) {
209 dsp::voice *v = *i;
210 v->render_to(output, nsamples);
211 if (!v->get_active()) {
212 i = active_voices.erase(i);
213 unused_voices.push(v);
214 continue;
216 i++;
220 basic_synth::~basic_synth()
222 while(!unused_voices.empty()) {
223 delete unused_voices.top();
224 unused_voices.pop();
226 for (list<voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
227 delete *i;