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