+ AUTHORS: updated
[calf.git] / src / synth.cpp
blob0f34ec0371076b499df1f509cc041d6c9bed6fe9
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., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, 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 for(std::list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
69 if ((*i)->get_priority() < priority)
71 priority = (*i)->get_priority();
72 found = i;
75 if (found == active_voices.end())
76 return NULL;
78 (*found)->steal();
79 return NULL;
82 void basic_synth::trim_voices()
84 // count stealable voices
85 unsigned int count = 0;
86 for(std::list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
88 if ((*i)->get_priority() < 10000)
89 count++;
91 // printf("Count=%d limit=%d\n", count, polyphony_limit);
92 // steal any voices above polyphony limit
93 if (count > polyphony_limit) {
94 for (unsigned int i = 0; i < count - polyphony_limit; i++)
95 steal_voice();
99 void basic_synth::note_on(int note, int vel)
101 if (!vel) {
102 note_off(note, 0);
103 return;
105 bool perc = check_percussion();
106 dsp::voice *v = give_voice();
107 v->setup(sample_rate);
108 v->released = false;
109 v->sostenuto = false;
110 gate.set(note);
111 v->note_on(note, vel);
112 active_voices.push_back(v);
113 if (perc) {
114 percussion_note_on(note, vel);
118 void basic_synth::note_off(int note, int vel)
120 gate.reset(note);
121 if (!hold)
122 kill_note(note, vel, false);
125 #define for_all_voices(iter) for (std::list<dsp::voice *>::iterator iter = active_voices.begin(); iter != active_voices.end(); iter++)
127 void basic_synth::on_pedal_release()
129 for_all_voices(i)
131 int note = (*i)->get_current_note();
132 if (note < 0 || note > 127)
133 continue;
134 bool still_held = gate[note];
135 // sostenuto pedal released
136 if ((*i)->sostenuto && !sostenuto)
138 // mark note as non-sostenuto
139 (*i)->sostenuto = false;
140 // 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)
141 // if key has been released and hold pedal is not depressed, release the note
142 if (!still_held && !hold)
143 (*i)->note_off(127);
145 else if (!hold && !still_held && !(*i)->released)
147 (*i)->released = true;
148 (*i)->note_off(127);
153 void basic_synth::control_change(int ctl, int val)
155 if (ctl == 64) { // HOLD controller
156 bool prev = hold;
157 hold = (val >= 64);
158 if (!hold && prev && !sostenuto) {
159 on_pedal_release();
162 if (ctl == 66) { // SOSTENUTO controller
163 bool prev = sostenuto;
164 sostenuto = (val >= 64);
165 if (sostenuto && !prev) {
166 // SOSTENUTO was pressed - move all notes onto sustain stack
167 for_all_voices(i) {
168 (*i)->sostenuto = true;
171 if (!sostenuto && prev) {
172 // SOSTENUTO was released - release all keys which were previously held
173 on_pedal_release();
176 if (ctl == 123 || ctl == 120) { // all notes off, all sounds off
177 vector<int> notes;
178 notes.reserve(128);
179 if (ctl == 120) { // for "all sounds off", automatically release hold and sostenuto pedal
180 control_change(66, 0);
181 control_change(64, 0);
183 for_all_voices(i)
185 (*i)->note_off(127);
188 if (ctl == 121) {
189 control_change(1, 0);
190 control_change(7, 100);
191 control_change(10, 64);
192 control_change(11, 127);
193 // release hold..hold2
194 for (int i = 64; i <= 69; i++)
195 control_change(i, 0);
199 void basic_synth::render_to(float (*output)[2], int nsamples)
201 // render voices, eliminate ones that aren't sounding anymore
202 for (list<dsp::voice *>::iterator i = active_voices.begin(); i != active_voices.end();) {
203 dsp::voice *v = *i;
204 v->render_to(output, nsamples);
205 if (!v->get_active()) {
206 i = active_voices.erase(i);
207 unused_voices.push(v);
208 continue;
210 i++;
214 basic_synth::~basic_synth()
216 while(!unused_voices.empty()) {
217 delete unused_voices.top();
218 unused_voices.pop();
220 for (list<voice *>::iterator i = active_voices.begin(); i != active_voices.end(); i++)
221 delete *i;