1 //=========================================================
2 // MusE
3 // Linux Music Editor
4 // $Id: sig.cpp,v 1.5.2.2 2009/03/09 02:05:17 terminator356 Exp $
5 //
6 // (C) Copyright 2000 Werner Schweer (ws@seh.de)
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; version 2 of
11 // the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //
22 //=========================================================
23
24 #include <stdio.h>
25 #include "sig.h"
26 #include "gconfig.h"
27
28 namespace MusEGlobal {
29 MusECore::SigList sigmap;
30 }
31
32 namespace MusECore {
33
34 //---------------------------------------------------------
35 //---------------------------------------------------------
36 // isValid
37 //---------------------------------------------------------
38
isValid() const39 bool TimeSignature::isValid() const
40 {
41 if((z < 1) || (z > 63))
42 return false;
43
44 switch(n)
45 {
46 case 1:
47 case 2:
48 case 3:
49 case 4:
50 case 8:
51 case 16:
52 case 32:
53 case 64:
54 case 128:
55 return true;
56 default:
57 return false;
58 }
59 }
60
61 //---------------------------------------------------------
62 // SigList
63 //---------------------------------------------------------
64
SigList()65 SigList::SigList()
66 {
67 insert(std::pair<const unsigned, SigEvent*> (MAX_TICK, new SigEvent(TimeSignature(4, 4), 0)));
68 }
69
~SigList()70 SigList::~SigList()
71 {
72 for (iSigEvent i = begin(); i != end(); ++i)
73 delete i->second;
74 }
75
76 //---------------------------------------------------------
77 // copy
78 //---------------------------------------------------------
79
copy(const SigList & src)80 void SigList::copy(const SigList& src)
81 {
82 // Clear and delete the existing destination list.
83 for (iSigEvent i = begin(); i != end(); ++i)
84 delete i->second;
85 SIGLIST::clear();
86
87 for (ciSigEvent i = src.cbegin(); i != src.cend(); ++i)
88 {
89 SigEvent* new_e = new SigEvent(*i->second);
90 std::pair<iSigEvent, bool> res = insert(std::pair<const unsigned, SigEvent*> (i->first, new_e));
91 if(!res.second)
92 {
93 fprintf(stderr, "SigList::copy insert failed: siglist:%p sig:%p %d/%d tick:%d\n",
94 this, new_e, new_e->sig.z, new_e->sig.n, new_e->tick);
95 }
96 }
97 }
98
99 //---------------------------------------------------------
100 // add
101 // signatures are only allowed at the beginning of
102 // a bar
103 //---------------------------------------------------------
104
add(unsigned tick,const TimeSignature & s,bool do_normalize)105 void SigList::add(unsigned tick, const TimeSignature& s, bool do_normalize)
106 {
107 if (s.z == 0 || s.n == 0) {
108 printf("illegal signature %d/%d\n", s.z, s.n);
109 return;
110 }
111 tick = raster1(tick, 0);
112 iSigEvent e = upper_bound(tick);
113 if(e == end())
114 {
115 printf("SigList::add Signal not found tick:%d\n", tick);
116 return;
117 }
118
119 if (tick == e->second->tick) {
120 e->second->sig = s;
121 }
122 else {
123 SigEvent* ne = e->second;
124 SigEvent* ev = new SigEvent(ne->sig, ne->tick);
125 ne->sig = s;
126 ne->tick = tick;
127 insert(std::pair<const unsigned, SigEvent*> (tick, ev));
128 }
129 if(do_normalize)
130 normalize();
131 }
132
add(unsigned tick,SigEvent * e,bool do_normalize)133 void SigList::add(unsigned tick, SigEvent* e, bool do_normalize)
134 {
135 TimeSignature ts = e->sig;
136 std::pair<iSigEvent, bool> res = insert(std::pair<const unsigned, SigEvent*> (tick, e));
137 if(!res.second)
138 {
139 fprintf(stderr, "SigList::add insert failed: siglist:%p sig:%p %d/%d tick:%d\n",
140 this, e, ts.z, ts.n, e->tick);
141 }
142 else
143 {
144 iSigEvent ise = res.first;
145 ++ise; // There is always a 'next' sig event - there is always one at index MAX_TICK.
146 SigEvent* ne = ise->second;
147
148 // Swap the values. (This is how the sig list works.)
149 e->sig = ne->sig;
150 e->tick = ne->tick;
151 ne->sig = ts;
152 ne->tick = tick;
153
154 if(do_normalize)
155 normalize();
156 }
157 }
158
159 //---------------------------------------------------------
160 // del
161 //---------------------------------------------------------
162
del(unsigned tick,bool do_normalize)163 void SigList::del(unsigned tick, bool do_normalize)
164 {
165 // printf("SigList::del(%d)\n", tick);
166 iSigEvent e = find(tick);
167 if (e == end()) {
168 printf("SigList::del(%d): not found\n", tick);
169 return;
170 }
171 iSigEvent ne = e;
172 ++ne;
173 if (ne == end()) {
174 printf("SigList::del() next event not found!\n");
175 return;
176 }
177 ne->second->sig = e->second->sig;
178 ne->second->tick = e->second->tick;
179 erase(e);
180 if(do_normalize)
181 normalize();
182 }
183
del(iSigEvent e,bool do_normalize)184 void SigList::del(iSigEvent e, bool do_normalize)
185 {
186 iSigEvent ne = e;
187 ++ne;
188 if (ne == end()) {
189 printf("SigList::del() HALLO\n");
190 return;
191 }
192 ne->second->sig = e->second->sig;
193 ne->second->tick = e->second->tick;
194 erase(e);
195 if(do_normalize)
196 normalize();
197 }
198
199 //---------------------------------------------------------
200 // SigList::normalize
201 //---------------------------------------------------------
202
normalize()203 void SigList::normalize()
204 {
205 TimeSignature sig(0, 0);
206 unsigned tick = 0;
207 iSigEvent ee;
208
209 for (iSigEvent e = begin(); e != end();) {
210 if (sig.z == e->second->sig.z && sig.n == e->second->sig.n) {
211 e->second->tick = tick;
212 erase(ee);
213 }
214 sig = e->second->sig;
215 ee = e;
216 tick = e->second->tick;
217 ++e;
218 }
219
220 int bar = 0;
221 for (iSigEvent e = begin(); e != end();) {
222 e->second->bar = bar;
223 int delta = e->first - e->second->tick;
224 int ticksB = ticks_beat(e->second->sig.n);
225 int ticksM = ticksB * e->second->sig.z;
226 bar += delta / ticksM;
227 if (delta % ticksM) // Teil eines Taktes
228 ++bar;
229 ++e;
230 }
231 }
232
233 //---------------------------------------------------------
234 // SigList::dump
235 //---------------------------------------------------------
236
dump() const237 void SigList::dump() const
238 {
239 printf("\nSigList:\n");
240 for (ciSigEvent i = begin(); i != end(); ++i) {
241 printf("%6d %06d Bar %3d %02d/%d\n",
242 i->first, i->second->tick,
243 i->second->bar, i->second->sig.z, i->second->sig.n);
244 }
245 }
246
clear()247 void SigList::clear()
248 {
249 for (iSigEvent i = begin(); i != end(); ++i)
250 delete i->second;
251 SIGLIST::clear();
252 insert(std::pair<const unsigned, SigEvent*> (MAX_TICK, new SigEvent(TimeSignature(4, 4), 0)));
253 }
254
255 //---------------------------------------------------------
256 // ticksMeasure
257 //---------------------------------------------------------
258
ticksMeasure(const TimeSignature & sig) const259 int SigList::ticksMeasure(const TimeSignature& sig) const
260 {
261 return ticks_beat(sig.n) * sig.z;
262 }
263
ticksMeasure(int Z,int N) const264 int SigList::ticksMeasure(int Z, int N) const
265 {
266 return ticks_beat(N) * Z;
267 }
268
ticksMeasure(unsigned tick) const269 int SigList::ticksMeasure(unsigned tick) const
270 {
271 ciSigEvent i = upper_bound(tick);
272 if (i == end()) {
273 printf("ticksMeasure: not found %d\n", tick);
274 return 0;
275 }
276 return ticksMeasure(i->second->sig);
277 }
278
279 //---------------------------------------------------------
280 // ticksBeat
281 //---------------------------------------------------------
282
ticksBeat(unsigned tick) const283 int SigList::ticksBeat(unsigned tick) const
284 {
285 ciSigEvent i = upper_bound(tick);
286 if(i == end())
287 {
288 printf("SigList::ticksBeat event not found! tick:%d\n", tick);
289 return 0;
290 }
291 return ticks_beat(i->second->sig.n);
292 }
293
ticks_beat(int n) const294 int SigList::ticks_beat(int n) const
295 {
296 int m = MusEGlobal::config.division;
297
298 switch (n) {
299 case 1: m <<= 2; break; // 1536
300 case 2: m <<= 1; break; // 768
301 case 3: m += m >> 1; break; // 384+192
302 case 4: break; // 384
303 case 8: m >>= 1; break; // 192
304 case 16: m >>= 2; break; // 96
305 case 32: m >>= 3; break; // 48
306 case 64: m >>= 4; break; // 24
307 case 128: m >>= 5; break; // 12
308 default: break;
309 }
310 return m;
311 }
312
313 //---------------------------------------------------------
314 // timesig
315 //---------------------------------------------------------
316
timesig(unsigned tick) const317 TimeSignature SigList::timesig(unsigned tick) const
318 {
319 ciSigEvent i = upper_bound(tick);
320 if (i == end()) {
321 printf("timesig(%d): not found\n", tick);
322 return TimeSignature(4,4);
323 }
324 return i->second->sig;
325 }
326
timesig(unsigned tick,int & z,int & n) const327 void SigList::timesig(unsigned tick, int& z, int& n) const
328 {
329 ciSigEvent i = upper_bound(tick);
330 if (i == end()) {
331 printf("timesig(%d): not found\n", tick);
332 z = 4;
333 n = 4;
334 }
335 else {
336 z = i->second->sig.z;
337 n = i->second->sig.n;
338 }
339 }
340
341 //---------------------------------------------------------
342 // tickValues
343 //---------------------------------------------------------
344
tickValues(unsigned t,int * bar,int * beat,unsigned * tick) const345 void SigList::tickValues(unsigned t, int* bar, int* beat, unsigned* tick) const
346 {
347 ciSigEvent e = upper_bound(t);
348 if (e == end()) {
349 fprintf(stderr, "tickValues(0x%x) not found(%zd)\n", t, size());
350 *bar = 0;
351 *beat = 0;
352 *tick = 0;
353 return;
354 }
355
356 int delta = t - e->second->tick;
357 int ticksB = ticks_beat(e->second->sig.n);
358 int ticksM = ticksB * e->second->sig.z;
359 *bar = e->second->bar + delta / ticksM;
360 int rest = delta % ticksM;
361 *beat = rest / ticksB;
362 *tick = rest % ticksB;
363 }
364
365 //---------------------------------------------------------
366 // bar2tick
367 //---------------------------------------------------------
368
bar2tick(int bar,int beat,unsigned tick) const369 unsigned SigList::bar2tick(int bar, int beat, unsigned tick) const
370 {
371 ciSigEvent e;
372
373 if (bar < 0)
374 bar = 0;
375 for (e = begin(); e != end();) {
376 ciSigEvent ee = e;
377 ++ee;
378 if (ee == end())
379 break;
380 if (bar < ee->second->bar)
381 break;
382 e = ee;
383 }
384 int ticksB = ticks_beat(e->second->sig.n);
385 int ticksM = ticksB * e->second->sig.z;
386 return e->second->tick + (bar-e->second->bar)*ticksM + ticksB*beat + tick;
387 }
388
389 //---------------------------------------------------------
390 // raster
391 //---------------------------------------------------------
392
raster(unsigned t,int raster) const393 unsigned SigList::raster(unsigned t, int raster) const
394 {
395 if (raster == 1)
396 return t;
397 ciSigEvent e = upper_bound(t);
398 if (e == end()) {
399 printf("SigList::raster(%x,)\n", t);
400 return t;
401 }
402 int delta = t - e->second->tick;
403 int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
404 // If the raster is on 'bar' or is greater than a full bar, we limit the raster to a full bar.
405 if (raster == 0 || raster > ticksM)
406 raster = ticksM;
407 int rest = delta % ticksM;
408 int bb = (delta/ticksM)*ticksM;
409 int rr = ((rest + raster/2)/raster)*raster;
410 // If the remaining length is less than a raster (ex. 4/4 + 4. snap) be sure to use that shorter length.
411 const int r_cur = (rest / raster) * raster;
412 const int len_cur = ticksM - r_cur;
413 if(len_cur < raster && rest >= (r_cur + len_cur / 2))
414 rr = ticksM;
415 return e->second->tick + bb + rr;
416 }
417
418 //---------------------------------------------------------
419 // raster1
420 // round down
421 //---------------------------------------------------------
422
raster1(unsigned t,int raster) const423 unsigned SigList::raster1(unsigned t, int raster) const
424 {
425 if (raster == 1)
426 return t;
427 ciSigEvent e = upper_bound(t);
428 if(e == end())
429 {
430 printf("SigList::raster1 event not found tick:%d\n", t);
431 return t;
432 }
433
434 int delta = t - e->second->tick;
435 int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
436 // If the raster is on 'bar' or is greater than a full bar, we limit the raster to a full bar.
437 if (raster == 0 || raster > ticksM)
438 raster = ticksM;
439 int rest = delta % ticksM;
440 int bb = (delta/ticksM)*ticksM;
441 return e->second->tick + bb + (rest/raster)*raster;
442 }
443
444 //---------------------------------------------------------
445 // raster2
446 // round up
447 //---------------------------------------------------------
448
raster2(unsigned t,int raster) const449 unsigned SigList::raster2(unsigned t, int raster) const
450 {
451 if (raster == 1)
452 return t;
453 ciSigEvent e = upper_bound(t);
454 if(e == end())
455 {
456 printf("SigList::raster2 event not found tick:%d\n", t);
457 return t;
458 }
459
460 int delta = t - e->second->tick;
461 int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
462 // If the raster is on 'bar' or is greater than a full bar, we limit the raster to a full bar.
463 if (raster == 0 || raster > ticksM)
464 raster = ticksM;
465 int rest = delta % ticksM;
466 int bb = (delta/ticksM)*ticksM;
467 int rr = ((rest+raster-1)/raster)*raster;
468 // If the result is beyond a bar (ex. last shorter division of 4/4 + 4. snap), limit to that bar.
469 if(rr > ticksM)
470 rr = ticksM;
471 return e->second->tick + bb + rr;
472 }
473
474 //---------------------------------------------------------
475 // rasterStep
476 //---------------------------------------------------------
477
rasterStep(unsigned t,int raster) const478 int SigList::rasterStep(unsigned t, int raster) const
479 {
480 ciSigEvent e = upper_bound(t);
481 if(e == end())
482 {
483 printf("SigList::rasterStep event not found tick:%d\n", t);
484 return raster;
485 }
486 const int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
487 // If the raster is on 'bar' or is greater than a full bar, we limit the raster to a full bar.
488 if (raster == 0 || raster > ticksM)
489 raster = ticksM;
490 return raster;
491 }
492
write(int level,MusECore::Xml & xml) const493 void SigList::write(int level, MusECore::Xml& xml) const
494 {
495 xml.tag(level++, "siglist");
496 for (ciSigEvent i = begin(); i != end(); ++i)
497 i->second->write(level, xml, i->first);
498 xml.tag(level, "/siglist");
499 }
500
read(MusECore::Xml & xml)501 void SigList::read(MusECore::Xml& xml)
502 {
503 for (;;) {
504 MusECore::Xml::Token token = xml.parse();
505 const QString& tag = xml.s1();
506 switch (token) {
507 case MusECore::Xml::Error:
508 case MusECore::Xml::End:
509 return;
510 case MusECore::Xml::TagStart:
511 if (tag == "sig") {
512 SigEvent* t = new SigEvent();
513 unsigned tick = t->read(xml);
514 iSigEvent pos = find(tick);
515 if (pos != end())
516 erase(pos);
517 insert(std::pair<const unsigned, SigEvent*> (tick, t));
518 }
519 else
520 xml.unknown("SigList");
521 break;
522 case MusECore::Xml::Attribut:
523 break;
524 case MusECore::Xml::TagEnd:
525 if (tag == "siglist") {
526 normalize();
527 return;
528 }
529 default:
530 break;
531 }
532 }
533 }
534
write(int level,MusECore::Xml & xml,int at) const535 void SigEvent::write(int level, MusECore::Xml& xml, int at) const
536 {
537 xml.tag(level++, "sig at=\"%d\"", at);
538 xml.intTag(level, "tick", tick);
539 xml.intTag(level, "nom", sig.z);
540 xml.intTag(level, "denom", sig.n);
541 xml.tag(level, "/sig");
542 }
543
read(MusECore::Xml & xml)544 int SigEvent::read(MusECore::Xml& xml)
545 {
546 int at = 0;
547 for (;;) {
548 MusECore::Xml::Token token = xml.parse();
549 const QString& tag = xml.s1();
550 switch (token) {
551 case MusECore::Xml::Error:
552 case MusECore::Xml::End:
553 return 0;
554 case MusECore::Xml::TagStart:
555 if (tag == "tick")
556 tick = xml.parseInt();
557 else if (tag == "nom")
558 sig.z = xml.parseInt();
559 else if (tag == "denom")
560 sig.n = xml.parseInt();
561 else
562 xml.unknown("SigEvent");
563 break;
564 case MusECore::Xml::Attribut:
565 if (tag == "at")
566 at = xml.s2().toInt();
567 break;
568 case MusECore::Xml::TagEnd:
569 if (tag == "sig")
570 return at;
571 default:
572 break;
573 }
574 }
575 return 0;
576 }
577
578 } // namespace MusECore
579