1 /*
2 Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <time.h>
20 #include "model.h"
21 #include "scales.h"
22 #include "global.h"
23 #include "aeolus.h"
24
25 #define VERSION "0.0.0"
26
27 //---------------------------------------------------------
28 // Divis
29 //---------------------------------------------------------
30
Divis()31 Divis::Divis() : _flags(0), _dmask(0), _nrank(0)
32 {
33 *_label = 0;
34 _param[SWELL].set("swell", SWELL_DEF, SWELL_MIN, SWELL_MAX);
35 _param[TFREQ].set("tfreq", TFREQ_DEF, TFREQ_MIN, TFREQ_MAX);
36 _param[TMODD].set("tmodd", TMODD_DEF, TMODD_MIN, TMODD_MAX);
37 }
38
Keybd()39 Keybd::Keybd() : _flags(0)
40 {
41 *_label = 0;
42 }
43
Ifelm()44 Ifelm::Ifelm() : _state(0)
45 {
46 _label[0] = 0;
47 _mnemo[0] = 0;
48 }
49
Group()50 Group::Group() : _nifelm(0)
51 {
52 _label[0] = 0;
53 }
54
55 //---------------------------------------------------------
56 // Model
57 //---------------------------------------------------------
58
Model(Aeolus * a,uint16_t * midimap,const char * stops,const char * instr,const char * waves)59 Model::Model (Aeolus* a,
60 uint16_t* midimap,
61 const char* stops,
62 const char* instr,
63 const char* waves)
64 :
65 _aeolus(a),
66 _midimap (midimap),
67 _stops (stops),
68 _ready (false),
69 _nasect (0),
70 _ndivis (0),
71 _nkeybd (0),
72 _ngroup (0),
73 _count (0),
74 _bank (0),
75 _pres (0),
76 _sc_cmode (0),
77 _sc_group (0)
78 {
79 sprintf (_instr, "%s/%s", stops, instr);
80 _waves = waves;
81 memset (_midimap, 0, 16 * sizeof (uint16_t));
82 memset (_preset, 0, NBANK * NPRES * sizeof (Preset *));
83 }
84
85 //---------------------------------------------------------
86 // init
87 //---------------------------------------------------------
88
init()89 void Model::init()
90 {
91 read_instr ();
92 read_presets ();
93
94 // init audio
95 Divis* D = _divis;
96 for (int d = 0; d < _ndivis; d++, D++) {
97 M_new_divis M;
98 M._flags = D->_flags;
99 M._dmask = D->_dmask;
100 M._asect = D->_asect;
101 M._swell = D->_param [Divis::SWELL].fval();
102 M._tfreq = D->_param [Divis::TFREQ].fval();
103 M._tmodd = D->_param [Divis::TMODD].fval();
104 _aeolus->newDivis(&M);
105 }
106
107 init_iface();
108 init_ranks(MT_LOAD_RANK);
109 init_ranks(MT_SAVE_RANK);
110 }
111
112 //---------------------------------------------------------
113 // init_iface
114 //---------------------------------------------------------
115
init_iface()116 void Model::init_iface()
117 {
118 M_ifc_init* M = new M_ifc_init;
119 _aeolus->_ifc_init = M;
120 M->_stops = _stops;
121 M->_waves = _waves;
122 M->_instr = _instr;
123 M->_client = 0; // _midi->_client;
124 M->_ipport = 0; // _midi->_ipport;
125 M->_nasect = _nasect;
126 M->_nkeybd = _nkeybd;
127 M->_ndivis = _ndivis;
128 M->_ngroup = _ngroup;
129 M->_ntempe = NSCALES;
130 for (int i = 0; i < NKEYBD; i++) {
131 Keybd* K = _keybd + i;
132 M->_keybdd [i]._label = K->_label;
133 M->_keybdd [i]._flags = K->_flags;
134 }
135 for (int i = 0; i < NDIVIS; i++) {
136 Divis* D = _divis + i;
137 M->_divisd [i]._label = D->_label;
138 M->_divisd [i]._flags = D->_flags;
139 M->_divisd [i]._asect = D->_asect;
140 }
141 for (int i = 0; i < NGROUP; i++) {
142 Group* G = _group + i;
143 M->_groupd [i]._label = G->_label;
144 M->_groupd [i]._nifelm = G->_nifelm;
145 for (int j = 0; j < G->_nifelm; j++) {
146 M->_groupd [i]._ifelmd [j]._label = G->_ifelms [j]._label;
147 M->_groupd [i]._ifelmd [j]._mnemo = G->_ifelms [j]._mnemo;
148 M->_groupd [i]._ifelmd [j]._type = G->_ifelms [j]._type;
149 }
150 }
151 for (int i = 0; i < NSCALES; i++) {
152 M->_temped [i]._label = scales [i]._label;
153 M->_temped [i]._mnemo = scales [i]._mnemo;
154 }
155
156 set_mconf (0, _chconf[0]._bits);
157 }
158
init_ranks(int comm)159 void Model::init_ranks (int comm)
160 {
161 _count++;
162 _ready = false;
163 //WS send_event (TO_IFACE, new M_ifc_retune (_fbase, _itemp));
164
165 for (int g = 0; g < _ngroup; g++) {
166 Group* G = _group + g;
167 for (int i = 0; i < G->_nifelm; i++)
168 proc_rank (g, i, comm);
169 }
170 _ready = true;
171 }
172
173
proc_rank(int g,int i,int comm)174 void Model::proc_rank (int g, int i, int comm)
175 {
176 Ifelm* I = _group [g]._ifelms + i;
177 if ((I->_type == Ifelm::DIVRANK) || (I->_type == Ifelm::KBDRANK)) {
178 int d = (I->_action0 >> 16) & 255;
179 int r = (I->_action0 >> 8) & 255;
180 Rank* R = _divis [d]._ranks + r;
181 if (comm == MT_SAVE_RANK) {
182 if (R->_wave->modif ()) {
183 R->_wave->save(_waves, R->_sdef, _aeolus->_fsamp,
184 _fbase, scales[_itemp]._data);
185 }
186 }
187 else if (R->_count != _count) {
188 R->_count = _count;
189 M_def_rank M(comm);
190 M._divis = d;
191 M._rank = r;
192 M._group = g;
193 M._ifelm = i;
194 M._fsamp = _aeolus->_fsamp;
195 M._fbase = _fbase;
196 M._scale = scales [_itemp]._data;
197 M._sdef = R->_sdef;
198 M._wave = R->_wave;
199 M._path = _waves;
200
201 //WS send_event(TO_IFACE, new M_ifc_ifelm (MT_IFC_ELATT, M._group, M._ifelm));
202
203 M._wave = new Rankwave (M._sdef->_n0, M._sdef->_n1);
204 if (M._wave->load (M._path, M._sdef, M._fsamp, M._fbase, M._scale))
205 M._wave->gen_waves (M._sdef, M._fsamp, M._fbase, M._scale);
206
207 _aeolus->_divisp [M._divis]->set_rank (M._rank, M._wave, M._sdef->_pan, M._sdef->_del);
208 _divis [M._divis]._ranks [M._rank]._wave = M._wave;
209 }
210 }
211 }
212
213 //---------------------------------------------------------
214 // set_ifelm
215 // Set, reset or toggle a stop.
216 // m - 0 reset
217 // 1 set
218 // 2 toggle
219 //---------------------------------------------------------
220
set_ifelm(int g,int i,int m)221 void Model::set_ifelm (int g, int i, int m)
222 {
223 Group* G = _group + g;
224
225 if (!_ready || (g >= _ngroup) || (i >= G->_nifelm)) {
226 printf("Aeolus::Model::set_ifelm failed, ready %d %d>=%d %d>=%d\n", _ready, g, _ngroup, i, G->_nifelm);
227 return;
228 }
229 Ifelm* I = G->_ifelms + i;
230 int s = (m == 2) ? I->_state ^ 1 : m;
231 if (I->_state != s) {
232 I->_state = s;
233 _aeolus->proc_queue(s ? I->_action1 : I->_action0);
234 M_ifc_ifelm* e = new M_ifc_ifelm (MT_IFC_ELCLR + s, g, i);
235 if (m == 0)
236 _aeolus->_ifelms [e->_group] &= ~(1 << e->_ifelm);
237 else if (m == 1)
238 _aeolus->_ifelms [e->_group] |= (1 << e->_ifelm);
239 else if (m == 2)
240 _aeolus->_ifelms [e->_group] = 0;
241 }
242 }
243
clr_group(int g)244 void Model::clr_group (int g)
245 {
246 Group* G = _group + g;
247
248 if ((! _ready) || (g >= _ngroup))
249 return;
250
251 for (int i = 0; i < G->_nifelm; i++) {
252 Ifelm* I = G->_ifelms + i;
253 if (I->_state) {
254 I->_state = 0;
255 _aeolus->proc_queue(I->_action0);
256 }
257 }
258 _aeolus->_ifelms[g] = 0;
259 }
260
261
262 //---------------------------------------------------------
263 // get_state
264 //---------------------------------------------------------
265
get_state(uint32_t * d)266 void Model::get_state(uint32_t* d)
267 {
268 for (int g = 0; g < _ngroup; g++) {
269 Group* G = _group + g;
270 uint32_t s = 0;
271 for (int i = 0; i < G->_nifelm; i++) {
272 Ifelm* I = G->_ifelms + i;
273 if (I->_state & 1)
274 s |= 1 << i;
275 }
276 *d++ = s;
277 }
278 }
279
280
281 //---------------------------------------------------------
282 // set_state
283 //---------------------------------------------------------
284
set_state(int bank,int pres)285 void Model::set_state(int bank, int pres)
286 {
287 uint32_t d[NGROUP];
288
289 _bank = bank;
290 _pres = pres;
291 if (get_preset(bank, pres, d)) {
292 for (int g = 0; g < _ngroup; g++) {
293 uint32_t s = d [g];
294 Group* G = _group + g;
295 for (int i = 0; i < G->_nifelm; i++) {
296 set_ifelm (g, i, s & 1);
297 s >>= 1;
298 }
299 }
300 }
301 }
302
303
set_mconf(int,uint16_t * d)304 void Model::set_mconf (int /*i*/, uint16_t *d)
305 {
306 midi_off(127);
307 for (int j = 0; j < 16; j++) {
308 int a = d [j];
309 int b = (a & 0x1000) ? (_keybd [a & 7]._flags & 127) : 0;
310 b |= a & 0x7700;
311 _midimap [j] = b;
312 }
313 }
314
315
midi_off(int mask)316 void Model::midi_off (int mask)
317 {
318 mask &= 127;
319 _aeolus->proc_queue((2 << 24) | (mask << 16) | mask);
320 }
321
322
retune(float freq,int temp)323 void Model::retune (float freq, int temp)
324 {
325 if (_ready)
326 {
327 _fbase = freq;
328 _itemp = temp;
329 init_ranks (MT_CALC_RANK);
330 }
331 else {
332 //WS send_event (TO_IFACE, new M_ifc_retune (_fbase, _itemp));
333 }
334 }
335
recalc(int g,int i)336 void Model::recalc (int g, int i)
337 {
338 _count++;
339 _ready = false;
340 proc_rank (g, i, MT_CALC_RANK);
341 }
342
343 #if 0
344 void Model::save ()
345 {
346 write_instr ();
347 writePresets();
348 _ready = false;
349 for (int g = 0; g < _ngroup; g++) {
350 Group* G = _group + g;
351 for (int i = 0; i < G->_nifelm; i++)
352 proc_rank (g, i, MT_SAVE_RANK);
353 }
354 }
355 #endif
356
find_rank(int g,int i)357 Rank *Model::find_rank (int g, int i)
358 {
359 Ifelm* I = _group [g]._ifelms + i;
360 if ((I->_type == Ifelm::DIVRANK) || (I->_type == Ifelm::KBDRANK)) {
361 int d = (I->_action0 >> 16) & 255;
362 int r = (I->_action0 >> 8) & 255;
363 return _divis [d]._ranks + r;
364 }
365 return 0;
366 }
367
368
read_instr()369 int Model::read_instr ()
370 {
371 int line, stat, n;
372 bool instr;
373 int d, k, r, s;
374 char c, *p, *q;
375 char t1 [256];
376 char t2 [256];
377 Keybd *K;
378 Divis *D;
379 Rank *R;
380 Group *G;
381 Ifelm *I;
382 Addsynth *A;
383
384 #undef ERROR
385 enum { CONT, DONE, ERROR, COMM, ARGS, MORE, NO_INSTR, IN_INSTR,
386 BAD_SCOPE, BAD_ASECT, BAD_RANK, BAD_DIVIS, BAD_KEYBD, BAD_IFACE,
387 BAD_STR1, BAD_STR2 };
388
389 QFile f(QString("%1/definition").arg(_instr));
390 if (!f.open(QIODevice::ReadOnly)) {
391 fprintf (stderr, "Can't open '%s' for reading\n", qPrintable(f.fileName()));
392 return 1;
393 }
394
395 stat = 0;
396 line = 0;
397 instr = false;
398 D = 0;
399 G = 0;
400 d = k = r = s = 0;
401 #ifdef WIN32
402 QByteArray bb;
403 while (!stat) {
404 line++;
405 bb = f.readLine(1024);
406 if(bb.isEmpty())
407 break;
408 p = bb.data();
409 #else
410 char buff [1024];
411 while (!stat && f.readLine(buff, 1024)) {
412 line++;
413 p = buff;
414 #endif
415 if (*p != '/') {
416 while (isspace (*p))
417 p++;
418 if ((*p > ' ') && (*p != '#')) {
419 fprintf (stderr, "Syntax error in line %d\n", line);
420 stat = COMM;
421 }
422 continue;
423 }
424
425 q = p;
426 while ((*q >= ' ') && !isspace (*q))
427 q++;
428 *q++ = 0;
429 while ((*q >= ' ') && isspace (*q))
430 q++;
431
432 if (! strcmp (p, "/instr/new")) {
433 if (instr)
434 stat = IN_INSTR;
435 else
436 instr = true;
437 }
438 else if (! instr) {
439 stat = NO_INSTR;
440 }
441 else if (! strcmp (p, "/instr/end")) {
442 instr = false;
443 stat = DONE;
444 }
445 else if (! strcmp (p, "/manual/new") || ! strcmp (p, "/pedal/new")) {
446 if (D || G)
447 stat = BAD_SCOPE;
448 else if (sscanf (q, "%s%n", t1, &n) != 1)
449 stat = ARGS;
450 else {
451 q += n;
452 if (_nkeybd == NKEYBD) {
453 fprintf (stderr, "Line %d: can't create more than %d keyboards\n", line, NKEYBD);
454 stat = ERROR;
455 }
456 else if (strlen (t1) > 15)
457 stat = BAD_STR1;
458 else {
459 k = _nkeybd++;
460 K = _keybd + k;
461 strcpy (K->_label, t1);
462 K->_flags = 1 << k;
463 if (p [1] == 'p')
464 K->_flags |= HOLD_MASK | Keybd::IS_PEDAL;
465 }
466 }
467 }
468 else if (! strcmp (p, "/divis/new")) {
469 if (D || G)
470 stat = BAD_SCOPE;
471 else if (sscanf (q, "%s%d%d%n", t1, &k, &s, &n) != 3)
472 stat = ARGS;
473 else
474 {
475 q += n;
476 if (_ndivis == NDIVIS)
477 {
478 fprintf (stderr, "Line %d: can't create more than %d divisions\n", line, NDIVIS);
479 stat = ERROR;
480 }
481 else if (strlen (t1) > 15) stat = BAD_STR1;
482 else if ((k < 0) || (k > _nkeybd)) stat = BAD_KEYBD;
483 else if ((s < 1) || (s > NASECT)) stat = BAD_ASECT;
484 else
485 {
486 D = _divis + _ndivis++;
487 strcpy (D->_label, t1);
488 if (_nasect < s) _nasect = s;
489 D->_asect = s - 1;
490 D->_keybd = k - 1;
491 if (k--) D->_dmask = _keybd [k]._flags & 127;
492 }
493 }
494 }
495 else if (! strcmp (p, "/divis/end"))
496 {
497 if (!D || G) stat = BAD_SCOPE;
498 else D = 0;
499 }
500 else if (! strcmp (p, "/group/new"))
501 {
502 if (D || G) stat = BAD_SCOPE;
503 else if (sscanf (q, "%s%n", t1, &n) != 1) stat = ARGS;
504 else
505 {
506 q += n;
507 if (_ngroup == NGROUP)
508 {
509 fprintf (stderr, "Line %d: can't create more than %d groups\n", line, NGROUP);
510 stat = ERROR;
511 }
512 else if (strlen (t1) > 15) stat = BAD_STR1;
513 else
514 {
515 G = _group + _ngroup++;
516 strcpy (G->_label, t1);
517 }
518 }
519 }
520 else if (! strcmp (p, "/group/end"))
521 {
522 if (D || !G) stat = BAD_SCOPE;
523 else G = 0;
524 }
525
526 else if (! strcmp (p, "/tuning")) {
527 if (D || G)
528 stat = BAD_SCOPE;
529 else {
530 int nargs = sscanf (q, "%f %d%n", &_fbase, &_itemp, &n);
531 if (nargs != 2)
532 stat = ARGS;
533 else
534 q += n;
535 }
536 }
537
538 else if (! strcmp (p, "/rank"))
539 {
540 if (!D && G) stat = BAD_SCOPE;
541 else if (sscanf (q, "%c%d%s%n", &c, &d, t1, &n) != 3) stat = ARGS;
542 else
543 {
544 q += n;
545 if (D->_nrank == Divis::NRANK)
546 {
547 fprintf (stderr, "Line %d: can't create more than %d ranks per division\n", line, Divis::NRANK);
548 stat = ERROR;
549 }
550 else if (strlen (t1) > 63) stat = BAD_STR1;
551 else
552 {
553 A = new Addsynth;
554 strcpy (A->_filename, t1);
555 if (A->load (_stops))
556 {
557 stat = ERROR;
558 delete A;
559 }
560 else
561 {
562 A->_pan = c;
563 A->_del = d;
564 R = D->_ranks + D->_nrank++;
565 R->_count = 0;
566 R->_sdef = A;
567 R->_wave = 0;
568 }
569 }
570 }
571 }
572 else if (! strcmp (p, "/tremul"))
573 {
574 if (D)
575 {
576 float val1;
577 float val2;
578 if (sscanf (q, "%f%f%n", &val1, &val2, &n) != 2)
579 stat = ARGS;
580 else {
581 D->_param[Divis::TFREQ].set(val1);
582 D->_param[Divis::TMODD].set(val2);
583 q += n;
584 D->_flags |= Divis::HAS_TREM;
585 }
586 }
587 else if (G)
588 {
589 if (sscanf (q, "%d%s%s%n", &d, t1, t2, &n) != 3) stat = ARGS;
590 else
591 {
592 q += n;
593 if (G->_nifelm == Group::NIFELM) stat = BAD_IFACE;
594 else if ((d < 1) || (d > _ndivis)) stat = BAD_DIVIS;
595 else if (strlen (t1) > 7) stat = BAD_STR1;
596 else if (strlen (t2) > 31) stat = BAD_STR2;
597 else
598 {
599 d--;
600 I = G->_ifelms + G->_nifelm++;
601 strcpy (I->_mnemo, t1);
602 strcpy (I->_label, t2);
603 I->_type = Ifelm::TREMUL;
604 I->_action0 = (16 << 24) | (d << 16) | 0;
605 I->_action1 = (16 << 24) | (d << 16) | 1;
606 }
607 }
608 }
609 else stat = BAD_SCOPE;
610 }
611 else if (! strcmp (p, "/swell"))
612 {
613 if (!D || G) stat = BAD_SCOPE;
614 else D->_flags |= Divis::HAS_SWELL;
615 }
616 else if (! strcmp (p, "/stop"))
617 {
618 if (D || !G) stat = BAD_SCOPE;
619 else if (sscanf (q, "%d%d%d%n", &k, &d, &r, &n) != 3) stat = ARGS;
620 else
621 {
622 q += n;
623 if (G->_nifelm == Group::NIFELM) stat = BAD_IFACE;
624 else if ((k < 0) || (k > _nkeybd)) stat = BAD_KEYBD;
625 else if ((d < 1) || (d > _ndivis)) stat = BAD_DIVIS;
626 else if ((r < 1) || (r > _divis [d - 1]._nrank)) stat = BAD_RANK;
627 else
628 {
629 k--;
630 d--;
631 r--;
632 I = G->_ifelms + G->_nifelm++;
633 R = _divis [d]._ranks + r;
634 strcpy (I->_label, R->_sdef->_stopname);
635 strcpy (I->_mnemo, R->_sdef->_mnemonic);
636 I->_keybd = k;
637 if (k >= 0)
638 {
639 I->_type = Ifelm::KBDRANK;
640 k = _keybd [k]._flags & 127;
641 }
642 else
643 {
644 I->_type = Ifelm::DIVRANK;
645 k = 128;
646 }
647 I->_action0 = (6 << 24) | (d << 16) | (r << 8) | k;
648 I->_action1 = (7 << 24) | (d << 16) | (r << 8) | k;
649 }
650 }
651 }
652 else if (! strcmp (p, "/coupler"))
653 {
654 if (D || !G) stat = BAD_SCOPE;
655 else if (sscanf (q, "%d%d%s%s%n", &k, &d, t1, t2, &n) != 4) stat = ARGS;
656 else
657 {
658 q += n;
659 if (G->_nifelm == Group::NIFELM) stat = BAD_IFACE;
660 else if ((k < 1) || (k > _nkeybd)) stat = BAD_KEYBD;
661 else if ((d < 1) || (d > _ndivis)) stat = BAD_DIVIS;
662 else if (strlen (t1) > 7) stat = BAD_STR1;
663 else if (strlen (t2) > 31) stat = BAD_STR2;
664 else
665 {
666 k--;
667 d--;
668 I = G->_ifelms + G->_nifelm++;
669 strcpy (I->_mnemo, t1);
670 strcpy (I->_label, t2);
671 I->_type = Ifelm::COUPLER;
672 I->_keybd = k;
673 k = _keybd [k]._flags & 127;
674 I->_action0 = (4 << 24) | (d << 16) | k;
675 I->_action1 = (5 << 24) | (d << 16) | k;
676 }
677 }
678 }
679 else stat = COMM;
680
681 if (stat <= DONE)
682 {
683 while (isspace (*q)) q++;
684 if (*q > ' ') stat = MORE;
685 }
686
687 switch (stat)
688 {
689 case COMM:
690 fprintf (stderr, "Line %d: unknown command '%s'\n", line, p);
691 break;
692 case ARGS:
693 fprintf (stderr, "Line %d: missing arguments in '%s' command\n", line, p);
694 break;
695 case MORE:
696 fprintf (stderr, "Line %d: extra arguments in '%s' command\n", line, p);
697 break;
698 case NO_INSTR:
699 fprintf (stderr, "Line %d: command '%s' outside instrument scope\n", line, p);
700 break;
701 case IN_INSTR:
702 fprintf (stderr, "Line %d: command '%s' inside instrument scope\n", line, p);
703 break;
704 case BAD_SCOPE:
705 fprintf (stderr, "Line %d: command '%s' in wrong scope\n", line, p);
706 break;
707 case BAD_ASECT:
708 fprintf (stderr, "Line %d: no section '%d'\n", line, s);
709 break;
710 case BAD_RANK:
711 fprintf (stderr, "Line %d: no rank '%d' in division '%d'\n", line, r, d);
712 break;
713 case BAD_KEYBD:
714 fprintf (stderr, "Line %d: no keyboard '%d'\n", line, k);
715 break;
716 case BAD_DIVIS:
717 fprintf (stderr, "Line %d: no division '%d'\n", line, d);
718 break;
719 case BAD_IFACE:
720 fprintf (stderr, "Line %d: can't create more than '%d' elements per group\n", line, Group::NIFELM);
721 break;
722 case BAD_STR1:
723 fprintf (stderr, "Line %d: string '%s' is too long\n", line, t1);
724 break;
725 case BAD_STR2:
726 fprintf (stderr, "Line %d: string '%s' is too long\n", line, t1);
727 break;
728 }
729 }
730
731 f.close();
732 return (stat <= DONE) ? 0 : 2;
733 }
734
735
736 int Model::write_instr()
737 {
738 FILE *F;
739 int d, g, i, k, r;
740 char buff [1024];
741 time_t t;
742 Divis *D;
743 Rank *R;
744 Group *G;
745 Ifelm *I;
746 Addsynth *A;
747
748 snprintf (buff, sizeof(buff), "%s/definition", _instr);
749 if (! (F = fopen (buff, "w")))
750 {
751 fprintf (stderr, "Can't open '%s' for writing\n", buff);
752 return 1;
753 }
754 printf ("Writing '%s'\n", buff);
755 t = time (0);
756
757 fprintf (F, "# Aeolus instrument definition file\n");
758 fprintf (F, "# Created by Aeolus-%s at %s\n", VERSION, ctime (&t));
759
760 fprintf (F, "\n/instr/new\n");
761 fprintf (F, "/tuning %5.1f %d\n", _fbase, _itemp);
762
763 fprintf (F, "\n# Keyboards\n#\n");
764 for (k = 0; k < _nkeybd; k++)
765 {
766 if (_keybd [k]._flags & Keybd::IS_PEDAL) fprintf (F, "/pedal/new %s\n", _keybd [k]._label);
767 else fprintf (F, "/manual/new %s\n", _keybd [k]._label);
768 }
769
770 fprintf (F, "\n# Divisions\n#\n");
771 for (d = 0; d < _ndivis; d++)
772 {
773 D = _divis + d;
774 fprintf (F, "/divis/new %-7s %d %d\n", D->_label, D->_keybd + 1, D->_asect + 1);
775 for (r = 0; r < D->_nrank; r++)
776 {
777 R = D->_ranks + r;
778 A = R->_sdef;
779 fprintf (F, "/rank %c %3d %s\n", A->_pan, A->_del, A->_filename);
780 }
781 if (D->_flags & Divis::HAS_SWELL) fprintf (F, "/swell\n");
782 if (D->_flags & Divis::HAS_TREM) fprintf (F, "/tremul %3.1f %3.1f\n",
783 D->_param [Divis::TFREQ].fval(), D->_param [Divis::TMODD].fval());
784 fprintf (F, "/divis/end\n\n");
785 }
786
787 fprintf (F, "# Interface groups\n#\n");
788 for (g = 0; g < _ngroup; g++)
789 {
790 G = _group + g;
791 fprintf (F, "/group/new %-7s\n", G->_label);
792 for (i = 0; i < G->_nifelm; i++)
793 {
794 I = G->_ifelms + i;
795 switch (I->_type)
796 {
797 case Ifelm::DIVRANK:
798 case Ifelm::KBDRANK:
799 k = I->_keybd;
800 d = (I->_action0 >> 16) & 255;
801 r = (I->_action0 >> 8) & 255;
802 fprintf (F, "/stop %d %d %2d\n", k + 1, d + 1, r + 1);
803 break;
804
805 case Ifelm::COUPLER:
806 k = I->_keybd;
807 d = (I->_action0 >> 16) & 255;
808 fprintf (F, "/coupler %d %d %-7s %s\n", k + 1, d + 1, I->_mnemo, I->_label);
809 break;
810
811 case Ifelm::TREMUL:
812 d = (I->_action0 >> 16) & 255;
813 D = _divis + d;
814 fprintf (F, "/tremul %d %-7s %s\n", d + 1, I->_mnemo, I->_label);
815 break;
816 }
817 }
818 fprintf (F, "/group/end\n\n");
819 }
820
821 fprintf (F, "\n/instr/end\n");
822 fclose (F);
823
824 return 0;
825 }
826
827 //---------------------------------------------------------
828 // get_preset
829 //---------------------------------------------------------
830
831 int Model::get_preset (int bank, int pres, uint32_t *bits)
832 {
833 if ((bank < 0) | (pres < 0) || (bank >= NBANK) || (pres >= NPRES))
834 return 0;
835 Preset* P = _preset [bank][pres];
836 if (P) {
837 for (int k = 0; k < _ngroup; k++)
838 *bits++ = P->_bits [k];
839 return _ngroup;
840 }
841 return 0;
842 }
843
844 //---------------------------------------------------------
845 // set_preset
846 //---------------------------------------------------------
847
848 void Model::set_preset (int bank, int pres, uint32_t *bits)
849 {
850 if ((bank < 0) | (pres < 0) || (bank >= NBANK) || (pres >= NPRES))
851 return;
852 Preset* P = _preset [bank][pres];
853 if (!P) {
854 P = new Preset;
855 _preset [bank][pres] = P;
856 }
857 for (int k = 0; k < _ngroup; k++)
858 P->_bits [k] = *bits++;
859 }
860
861 //---------------------------------------------------------
862 // ins_preset
863 //---------------------------------------------------------
864
865 void Model::ins_preset (int bank, int pres, uint32_t *bits)
866 {
867 if ((bank < 0) | (pres < 0) || (bank >= NBANK) || (pres >= NPRES))
868 return;
869 Preset* P = _preset [bank][NPRES - 1];
870 for (int j = NPRES - 1; j > pres; j--)
871 _preset [bank][j] = _preset [bank][j - 1];
872 if (!P) {
873 P = new Preset;
874 _preset [bank][pres] = P;
875 }
876 for (int k = 0; k < _ngroup; k++)
877 P->_bits [k] = *bits++;
878 }
879
880 //---------------------------------------------------------
881 // del_preset
882 //---------------------------------------------------------
883
884 void Model::del_preset (int bank, int pres)
885 {
886 if ((bank < 0) | (pres < 0) || (bank >= NBANK) || (pres >= NPRES))
887 return;
888 delete _preset [bank][pres];
889 for (int j = pres; j < NPRES - 1; j++)
890 _preset [bank][j] = _preset [bank][j + 1];
891 _preset [bank][NPRES - 1] = 0;
892 }
893
894 //---------------------------------------------------------
895 // read_presets
896 //---------------------------------------------------------
897
898 int Model::read_presets()
899 {
900 char name [1024];
901 uchar data [256];
902
903 QFile f(QString("%1/presets").arg(_instr));
904 if (!f.open(QIODevice::ReadOnly)) {
905 fprintf (stderr, "Can't open '%s' for reading\n", qPrintable(f.fileName()));
906 return 1;
907 }
908
909 f.read((char*)data, 16);
910 if (strcmp ((char *) data, "PRESET") || data [7]) {
911 fprintf (stderr, "File '%s' is not a valid preset file\n", name);
912 f.close();
913 return 1;
914 }
915 int n = RD2 (data + 14);
916
917 if (f.read ((char*)data, 256) != 256) {
918 fprintf (stderr, "No valid data in file '%s'\n", name);
919 f.close();
920 return 1;
921 }
922 // printf("==read_presets: chconf\n");
923 uchar* p = data;
924 for (int i = 0; i < 8; i++) {
925 for (int j = 0; j < 16; j++) {
926 int val = RD2(p);
927 // printf(" %d %d = %d\n", i, j, val);
928 _chconf [i]._bits [j] = val;
929 p += 2;
930 }
931 }
932 if (n != _ngroup) {
933 fprintf (stderr, "Presets in file '%s' are not compatible\n", name);
934 f.close();
935 return 1;
936 }
937 while (f.read ((char*)data, 4 + 4 * _ngroup) == 4 + 4 * _ngroup) {
938 p = data;
939 int i = *p++;
940 int j = *p++;
941 p++;
942 p++;
943 if ((i < NBANK) && (j < NPRES)) {
944 Preset* P = new Preset;
945 for (int k = 0; k < _ngroup; k++) {
946 P->_bits [k] = RD4 (p);
947 p += 4;
948 }
949 _preset [i][j] = P;
950 }
951 }
952 f.close();
953 return 0;
954 }
955
956 //---------------------------------------------------------
957 // write_presets
958 //---------------------------------------------------------
959
960 bool Model::writePresets()
961 {
962 char name [1024];
963 uchar data [256];
964 FILE *F;
965
966 snprintf (name, sizeof(name), "%s/presets", _instr);
967 if (! (F = fopen (name, "w"))) {
968 fprintf (stderr, "Can't open '%s' for writing\n", name);
969 return 1;
970 }
971
972 strcpy ((char *) data, "PRESET");
973 data [7] = 0;
974 WR2 (data + 8, 0);
975 WR2 (data + 10, 0);
976 WR2 (data + 12, 0);
977 WR2 (data + 14, _ngroup);
978 fwrite (data, 16, 1, F);
979
980 uchar* p = data;
981 for (int i = 0; i < 8; i++) {
982 for (int j = 0; j < 16; j++) {
983 int v = _chconf [i]._bits [j];
984 WR2 (p, v);
985 p += 2;
986 }
987 }
988 fwrite (data, 256, 1, F);
989
990 for (int i = 0; i < NBANK; i++) {
991 for (int j = 0; j < NPRES; j++) {
992 Preset* P = _preset [i][j];
993 if (P) {
994 p = data;
995 *p++ = i;
996 *p++ = j;
997 *p++ = 0;
998 *p++ = 0;
999 for (int k = 0; k < _ngroup; k++) {
1000 int v = P->_bits [k];
1001 WR4 (p, v);
1002 p += 4;
1003 }
1004 fwrite (data, 4 + 4 * _ngroup, 1, F);
1005 }
1006 }
1007 }
1008 fclose (F);
1009 return 0;
1010 }
1011
1012