1 //=========================================================
2 // MusE
3 // Linux Music Editor
4 // $Id: s1.cpp,v 1.9.2.5 2009/11/19 04:20:33 terminator356 Exp $
5 //
6 // S1 - simple mono demo synthesizer
7 // - plays only one note at a time
8 // - has no gui nor any controller
9 //
10 // Version 0.2: stop note on wave zero crossing to avoid
11 // clicks
12 //
13 // (C) Copyright 2001-2004 Werner Schweer (ws@seh.de)
14 //
15 // This program is free software; you can redistribute it and/or
16 // modify it under the terms of the GNU General Public License
17 // as published by the Free Software Foundation; version 2 of
18 // the License, or (at your option) any later version.
19 //
20 // This program is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software
27 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 //
29 //=========================================================
30
31 #include <list>
32
33 #include <QMessageBox>
34
35 #include "muse_math.h"
36 #include "libsynti/mono.h"
37
38 #define RESOLUTION 16384
39 // Make sure this number is unique among all the MESS synths (including ticksynth) and DSSI, VST, LV2 and other host synths.
40 // 127 is reserved for special MusE system messages.
41 #define S1_UNIQUE_ID 6
42
43
44 //---------------------------------------------------------
45 // S1 - simple mono demo synthesizer
46 //---------------------------------------------------------
47
48
49 class S1 : public MessMono {
50 static int useCount;
51 static float *wave_table;
52
53 int gate;
54 float freq;
55 unsigned accu;
56 float sample;
57 bool _showGui;
58
59 int param;
60
61 virtual void note(int channel, int pitch, int velo);
62 //virtual void processMessages();
63 virtual void process(unsigned pos, float** buffer, int offset, int n);
hasNativeGui() const64 virtual bool hasNativeGui() const { return true; }
nativeGuiVisible() const65 virtual bool nativeGuiVisible() const { return _showGui; }
66 virtual void showNativeGui(bool);
67 virtual bool setController(int channel, int ctrl, int val);
68 virtual int getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval) const;
69
70 public:
71 S1();
72 virtual ~S1();
73 };
74
75 float* S1::wave_table;
76 int S1::useCount = 0;
77
78 //---------------------------------------------------------
79 // S1
80 //---------------------------------------------------------
81
S1()82 S1::S1() : MessMono()
83 {
84
85 if (useCount++ == 0) {
86 //
87 // create sinus wave table
88 //
89 wave_table = new float[RESOLUTION];
90 for (int i = 0; i < RESOLUTION; i++)
91 wave_table[i] = sin ((i * 2.0 * M_PI) / RESOLUTION) / 6.0;
92 }
93 gate = 0;
94
95 param = 0;
96
97 _showGui=false;
98 showNativeGui(true);
99 }
100
101 //---------------------------------------------------------
102 // ~S1
103 //---------------------------------------------------------
104
~S1()105 S1::~S1()
106 {
107 if (--useCount == 0)
108 delete[] wave_table;
109 }
110
111 //---------------------------------------------------------
112 // noteon
113 // process note on
114 //---------------------------------------------------------
115
note(int,int pitch,int velo)116 void S1::note(int /*channel*/, int pitch, int velo)
117 {
118 if (velo == 0) {
119 //
120 // note off
121 //
122 if (sample == 0.0)
123 gate = 0;
124 else if (sample > 0.0)
125 gate = 2;
126 else if (sample < 0.0)
127 gate = 3;
128 }
129 else {
130 //
131 // note on
132 //
133 accu = 0;
134 gate = 1;
135 freq = 8.176 * exp(float(pitch)*log(2.0)/12.0);
136 }
137 }
138
139 //---------------------------------------------------------
140 // write
141 // synthesize n samples into buffer+offset
142 //---------------------------------------------------------
143
process(unsigned,float ** buffer,int offset,int n)144 void S1::process(unsigned /*pos*/, float** buffer, int offset, int n)
145 {
146 if (gate == 0)
147 return;
148 float* p = buffer[0] + offset;
149 float sample1, sample2;
150 unsigned freq_256 = (int) (freq * ((double) RESOLUTION) / sampleRate() * 256.0);
151 for (int i = 0; i < n; i++) {
152 accu += freq_256;
153 while (accu >= RESOLUTION * 256)
154 accu -= RESOLUTION * 256;
155
156 sample1 = wave_table[accu >> 8]; // sinus component
157
158 if (sample1< 0.0f) // square wave component
159 sample2 = -0.4;
160 else
161 sample2 = 0.4;
162
163 sample = ((1.0-float(param)/127.0)*sample1 + (float(param)/127.0)*sample2) / 2.0;
164
165 //
166 // stop on zero crossing
167 // if in decay state
168 //
169 if (gate == 2 && sample <= 0.0) {
170 gate = 0;
171 break;
172 }
173 else if (gate == 3 && sample >= 0.0) {
174 gate = 0;
175 break;
176 }
177 p[i] += sample;
178 }
179 }
180
181
182 //---------------------------------------------------------
183 // inst
184 //---------------------------------------------------------
185
186
showNativeGui(bool show)187 void S1::showNativeGui(bool show)
188 {
189 if (show)
190 QMessageBox::information( NULL, "S1",
191 "S1 is a demo synth mainly for\n"
192 "developers wishing to learn\n"
193 "how to make a M.E.S.S synth.\n"
194 "\n"
195 "One modulation parameter is available,\n"
196 "it sweeps the signal between square and\n"
197 "sinus wave.\n", 1 );
198 }
199
setController(int,int ctrl,int val)200 bool S1::setController(int, int ctrl, int val)
201 {
202 if (ctrl == 1) {
203 param = val;
204 }
205 return true;
206 }
207
getControllerInfo(int id,const char ** name,int * ctrl,int * min,int * max,int * initval) const208 int S1::getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval) const
209 {
210 if (id == 0) {
211 *name = "Modulation";
212 *ctrl = 1;
213 *min = 0;
214 *max = 127;
215 *initval = 0;
216 return 1;
217 }
218 else
219 return 0;
220 }
221
222 //---------------------------------------------------------
223 // inst
224 //---------------------------------------------------------
225 class QWidget;
226
227
instantiate(unsigned long long,const char *,const MessConfig * config)228 static Mess* instantiate(unsigned long long /*parentWinId*/, const char* /*name*/, const MessConfig* config)
229 {
230 S1* s1 = new S1();
231 s1->setSampleRate(config->_sampleRate);
232 return s1;
233 }
234
235 extern "C" {
236 static MESS descriptor = {
237 "S1",
238 "S1 MusE Demo Software Synthesizer",
239 "0.2", // version string
240 MESS_MAJOR_VERSION, MESS_MINOR_VERSION,
241 instantiate
242 };
243 // We must compile with -fvisibility=hidden to avoid namespace
244 // conflicts with global variables.
245 // Only visible symbol is "mess_descriptor".
246 // (TODO: all plugins should be compiled this way)
247
248 __attribute__ ((visibility("default")))
mess_descriptor()249 const MESS* mess_descriptor() { return &descriptor; }
250 }
251
252