summaryrefslogtreecommitdiff
path: root/muse/al
diff options
context:
space:
mode:
authorWerner Schweer <ws.seh.de>2006-05-03 12:42:25 +0000
committerWerner Schweer <ws.seh.de>2006-05-03 12:42:25 +0000
commitb125dd455e563bf098d8d59d20202985b76103a9 (patch)
tree6cb0785cba4966ed46a3a6a8891ce5098a7e151a /muse/al
initial import
Diffstat (limited to 'muse/al')
-rw-r--r--muse/al/CMakeLists.txt14
-rw-r--r--muse/al/al.cpp28
-rw-r--r--muse/al/al.h33
-rw-r--r--muse/al/marker.cpp86
-rw-r--r--muse/al/marker.h67
-rw-r--r--muse/al/pos.cpp581
-rw-r--r--muse/al/pos.h128
-rw-r--r--muse/al/sig.cpp407
-rw-r--r--muse/al/sig.h103
-rw-r--r--muse/al/tempo.cpp393
-rw-r--r--muse/al/tempo.h100
-rw-r--r--muse/al/xml.cpp344
-rw-r--r--muse/al/xml.h62
13 files changed, 2346 insertions, 0 deletions
diff --git a/muse/al/CMakeLists.txt b/muse/al/CMakeLists.txt
new file mode 100644
index 00000000..15f83580
--- /dev/null
+++ b/muse/al/CMakeLists.txt
@@ -0,0 +1,14 @@
+#
+#
+#
+#
+
+add_library(al STATIC
+ al.cpp marker.cpp pos.cpp sig.cpp tempo.cpp xml.cpp
+ )
+set_target_properties( al
+ PROPERTIES COMPILE_FLAGS "-include ${PROJECT_SOURCE_DIR}/all.h"
+ )
+
+add_dependencies(al ${PROJECT_SOURCE_DIR}/all.h.pch)
+
diff --git a/muse/al/al.cpp b/muse/al/al.cpp
new file mode 100644
index 00000000..af141170
--- /dev/null
+++ b/muse/al/al.cpp
@@ -0,0 +1,28 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al.h"
+
+namespace AL {
+ int sampleRate = 44100;
+ int mtcType = 0;
+ int division = 384;
+ };
+
diff --git a/muse/al/al.h b/muse/al/al.h
new file mode 100644
index 00000000..4f4e71a4
--- /dev/null
+++ b/muse/al/al.h
@@ -0,0 +1,33 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AL_H__
+#define __AL_H__
+
+namespace AL {
+
+ extern int sampleRate;
+ extern int mtcType;
+ extern int division;
+
+ }
+
+#endif
+
diff --git a/muse/al/marker.cpp b/muse/al/marker.cpp
new file mode 100644
index 00000000..2a0a4a0a
--- /dev/null
+++ b/muse/al/marker.cpp
@@ -0,0 +1,86 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "marker.h"
+#include "xml.h"
+
+namespace AL {
+
+//---------------------------------------------------------
+// add
+//---------------------------------------------------------
+
+Marker* MarkerList::add(const Marker& marker)
+ {
+ iMarker i = insert(std::pair<const int, Marker> (marker.tick(), Marker(marker)));
+ return &i->second;
+ }
+
+Marker* MarkerList::add(const QString& s, const Pos& pos)
+ {
+ Marker marker(pos);
+ marker.setName(s);
+ iMarker i = insert(std::pair<const int, Marker> (pos.tick(), marker));
+ return &i->second;
+ }
+
+//---------------------------------------------------------
+// read
+//---------------------------------------------------------
+
+void Marker::read(QDomNode node)
+ {
+ Pos::read(node);
+ QDomElement e = node.toElement();
+ _name = e.attribute("name");
+ }
+
+//---------------------------------------------------------
+// write
+//---------------------------------------------------------
+
+void MarkerList::write(Xml& xml) const
+ {
+ for (ciMarker i = begin(); i != end(); ++i) {
+ const Marker& m = i->second;
+ if (m.type() == TICKS)
+ xml.tagE("marker tick=\"%d\" name=\"%s\"", m.tick(), m.name().toLatin1().data());
+ else
+ xml.tagE("marker sample=\"%d\" name=\"%s\"", m.frame(), m.name().toLatin1().data());
+ }
+ }
+
+//---------------------------------------------------------
+// remove
+//---------------------------------------------------------
+
+void MarkerList::remove(Marker* m)
+ {
+ for (iMarker i = begin(); i != end(); ++i) {
+ Marker* mm = &i->second;
+ if (mm == m) {
+ erase(i);
+ return;
+ }
+ }
+ printf("MarkerList::remove(): marker not found\n");
+ }
+}
+
diff --git a/muse/al/marker.h b/muse/al/marker.h
new file mode 100644
index 00000000..7c77f72e
--- /dev/null
+++ b/muse/al/marker.h
@@ -0,0 +1,67 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __MARKER_H__
+#define __MARKER_H__
+
+#include "pos.h"
+
+namespace AL {
+ class Xml;
+
+//---------------------------------------------------------
+// Marker
+//---------------------------------------------------------
+
+class Marker : public Pos {
+ QString _name;
+ bool _current;
+
+ public:
+ Marker() : _current(false) {}
+ Marker(const Pos& m) : Pos(m), _current(false) {}
+ Marker(const QString& s, bool cur = false)
+ : _name(s), _current(cur) {}
+ void read(QDomNode);
+ const QString name() const { return _name; }
+ void setName(const QString& s) { _name = s; }
+ bool current() const { return _current; }
+ void setCurrent(bool f) { _current = f; }
+ };
+
+//---------------------------------------------------------
+// MarkerList
+//---------------------------------------------------------
+
+class MarkerList : public std::multimap<unsigned, Marker, std::less<unsigned> > {
+ public:
+ Marker* add(const Marker& m);
+ Marker* add(const QString& s, const Pos&);
+ void write(Xml&) const;
+ void remove(Marker*);
+ };
+
+typedef std::multimap<unsigned, Marker, std::less<unsigned> >::iterator iMarker;
+typedef std::multimap<unsigned, Marker, std::less<unsigned> >::const_iterator ciMarker;
+
+} // end namespace AL
+
+#endif
+
diff --git a/muse/al/pos.cpp b/muse/al/pos.cpp
new file mode 100644
index 00000000..7c6e6c8e
--- /dev/null
+++ b/muse/al/pos.cpp
@@ -0,0 +1,581 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al.h"
+#include "pos.h"
+#include "xml.h"
+#include "tempo.h"
+#include "sig.h"
+
+namespace AL {
+
+//---------------------------------------------------------
+// Pos
+//---------------------------------------------------------
+
+Pos::Pos()
+ {
+ _type = TICKS;
+ _tick = 0;
+ _frame = 0;
+ sn = -1;
+ }
+
+Pos::Pos(const Pos& p)
+ {
+ _type = p._type;
+ sn = p.sn;
+ _tick = p._tick;
+ _frame = p._frame;
+ }
+
+Pos::Pos(unsigned t, TType timeType)
+ {
+ _type = timeType;
+ if (_type == TICKS)
+ _tick = t;
+ else
+ _frame = t;
+ sn = -1;
+ }
+
+Pos::Pos(const QString& s)
+ {
+ int m, b, t;
+ sscanf(s.toLatin1().data(), "%04d.%02d.%03d", &m, &b, &t);
+ _tick = sigmap.bar2tick(m, b, t);
+ _type = TICKS;
+ sn = -1;
+ }
+
+Pos::Pos(int measure, int beat, int tick)
+ {
+ _tick = sigmap.bar2tick(measure, beat, tick);
+ _type = TICKS;
+ sn = -1;
+ }
+
+Pos::Pos(int min, int sec, int frame, int subframe)
+ {
+ double time = min * 60.0 + sec;
+
+ double f = frame + subframe/100.0;
+ switch (AL::mtcType) {
+ case 0: // 24 frames sec
+ time += f * 1.0/24.0;
+ break;
+ case 1: // 25
+ time += f * 1.0/25.0;
+ break;
+ case 2: // 30 drop frame
+ time += f * 1.0/30.0;
+ break;
+ case 3: // 30 non drop frame
+ time += f * 1.0/30.0;
+ break;
+ }
+ _type = FRAMES;
+ _frame = lrint(time * AL::sampleRate);
+ sn = -1;
+ }
+
+//---------------------------------------------------------
+// setType
+//---------------------------------------------------------
+
+void Pos::setType(TType t)
+ {
+ if (t == _type)
+ return;
+
+ if (_type == TICKS) {
+ // convert from ticks to frames
+ _frame = tempomap.tick2frame(_tick, _frame, &sn);
+ }
+ else {
+ // convert from frames to ticks
+ _tick = tempomap.frame2tick(_frame, _tick, &sn);
+ }
+ _type = t;
+ }
+
+//---------------------------------------------------------
+// operator+=
+//---------------------------------------------------------
+
+Pos& Pos::operator+=(const Pos& a)
+ {
+ if (_type == FRAMES)
+ _frame += a.frame();
+ else
+ _tick += a.tick();
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+//---------------------------------------------------------
+// operator-=
+//---------------------------------------------------------
+
+Pos& Pos::operator-=(const Pos& a)
+ {
+ if (_type == FRAMES)
+ _frame -= a.frame();
+ else
+ _tick -= a.tick();
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+//---------------------------------------------------------
+// operator+=
+//---------------------------------------------------------
+
+Pos& Pos::operator+=(int a)
+ {
+ if (_type == FRAMES)
+ _frame += a;
+ else
+ _tick += a;
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+//---------------------------------------------------------
+// operator-=
+//---------------------------------------------------------
+
+Pos& Pos::operator-=(int a)
+ {
+ if (_type == FRAMES)
+ _frame -= a;
+ else
+ _tick -= a;
+ sn = -1; // invalidate cached values
+ return *this;
+ }
+
+Pos operator+(const Pos& a, int b)
+ {
+ Pos c(a);
+ return c += b;
+ }
+
+Pos operator-(const Pos& a, int b)
+ {
+ Pos c(a);
+ return c -= b;
+ }
+
+Pos operator+(const Pos& a, const Pos& b)
+ {
+ Pos c(a);
+ return c += b;
+ }
+
+Pos operator-(const Pos& a, const Pos& b)
+ {
+ Pos c(a);
+ return c -= b;
+ }
+
+bool Pos::operator>=(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame >= s.frame();
+ else
+ return _tick >= s.tick();
+ }
+
+bool Pos::operator>(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame > s.frame();
+ else
+ return _tick > s.tick();
+ }
+
+bool Pos::operator<(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame < s.frame();
+ else
+ return _tick < s.tick();
+ }
+
+bool Pos::operator<=(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame <= s.frame();
+ else
+ return _tick <= s.tick();
+ }
+
+bool Pos::operator==(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame == s.frame();
+ else
+ return _tick == s.tick();
+ }
+
+bool Pos::operator!=(const Pos& s) const
+ {
+ if (_type == FRAMES)
+ return _frame != s.frame();
+ else
+ return _tick != s.tick();
+ }
+
+//---------------------------------------------------------
+// tick
+//---------------------------------------------------------
+
+unsigned Pos::tick() const
+ {
+ if (_type == FRAMES)
+ _tick = tempomap.frame2tick(_frame, _tick, &sn);
+ return _tick;
+ }
+
+//---------------------------------------------------------
+// frame
+//---------------------------------------------------------
+
+unsigned Pos::frame() const
+ {
+ if (_type == TICKS)
+ _frame = tempomap.tick2frame(_tick, _frame, &sn);
+ return _frame;
+ }
+
+//---------------------------------------------------------
+// setTick
+//---------------------------------------------------------
+
+void Pos::setTick(unsigned pos)
+ {
+ _tick = pos;
+ sn = -1;
+ if (_type == FRAMES)
+ _frame = tempomap.tick2frame(pos, &sn);
+ }
+
+//---------------------------------------------------------
+// setFrame
+//---------------------------------------------------------
+
+void Pos::setFrame(unsigned pos)
+ {
+ _frame = pos;
+ sn = -1;
+ if (_type == TICKS)
+ _tick = tempomap.frame2tick(pos, &sn);
+ }
+
+//---------------------------------------------------------
+// write
+//---------------------------------------------------------
+
+void Pos::write(Xml& xml, const char* name) const
+ {
+ if (_type == TICKS)
+ xml.tagE("%s tick=\"%d\"", name, _tick);
+ else
+ xml.tagE("%s frame=\"%d\"", name, _frame);
+ }
+
+//---------------------------------------------------------
+// read
+//---------------------------------------------------------
+
+void Pos::read(QDomNode node)
+ {
+ sn = -1;
+
+ QDomElement e = node.toElement();
+ QString s;
+ s = e.attribute("tick");
+ if (!s.isEmpty()) {
+ _tick = s.toInt();
+ _type = TICKS;
+ }
+ s = e.attribute("frame");
+ if (!s.isEmpty()) {
+ _frame = s.toInt();
+ _type = FRAMES;
+ }
+ }
+
+//---------------------------------------------------------
+// PosLen
+//---------------------------------------------------------
+
+PosLen::PosLen()
+ {
+ _lenTick = 0;
+ _lenFrame = 0;
+ sn = -1;
+ }
+
+PosLen::PosLen(const PosLen& p)
+ : Pos(p)
+ {
+ _lenTick = p._lenTick;
+ _lenFrame = p._lenFrame;
+ sn = -1;
+ }
+
+//---------------------------------------------------------
+// dump
+//---------------------------------------------------------
+
+void PosLen::dump(int n) const
+ {
+ Pos::dump(n);
+ printf(" Len(");
+ switch(type()) {
+ case FRAMES:
+ printf("samples=%d)\n", _lenFrame);
+ break;
+ case TICKS:
+ printf("ticks=%d)\n", _lenTick);
+ break;
+ }
+ }
+
+void Pos::dump(int /*n*/) const
+ {
+ printf("Pos(%s, sn=%d, ", type() == FRAMES ? "Frames" : "Ticks", sn);
+ switch(type()) {
+ case FRAMES:
+ printf("samples=%d)", _frame);
+ break;
+ case TICKS:
+ printf("ticks=%d)", _tick);
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// write
+//---------------------------------------------------------
+
+void PosLen::write(Xml& xml, const char* name) const
+ {
+ if (type() == TICKS)
+ xml.tagE("%s tick=\"%d\" len=\"%d\"", name, tick(), _lenTick);
+ else
+ xml.tagE("%s sample=\"%d\" len=\"%d\"", name, frame(), _lenFrame);
+ }
+
+//---------------------------------------------------------
+// read
+//---------------------------------------------------------
+
+void PosLen::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ QString s;
+ s = e.attribute("tick");
+ if (!s.isEmpty()) {
+ setType(TICKS);
+ setTick(s.toInt());
+ }
+ s = e.attribute("sample");
+ if (!s.isEmpty()) {
+ setType(FRAMES);
+ setFrame(s.toInt());
+ }
+ s = e.attribute("len");
+ if (!s.isEmpty()) {
+ int n = s.toInt();
+ if (type() == TICKS)
+ setLenTick(n);
+ else
+ setLenFrame(n);
+ }
+ }
+
+//---------------------------------------------------------
+// setLenTick
+//---------------------------------------------------------
+
+void PosLen::setLenTick(unsigned len)
+ {
+ _lenTick = len;
+ sn = -1;
+// if (type() == FRAMES)
+ _lenFrame = tempomap.tick2frame(len, &sn);
+ }
+
+//---------------------------------------------------------
+// setLenFrame
+//---------------------------------------------------------
+
+void PosLen::setLenFrame(unsigned len)
+ {
+ _lenFrame = len;
+ sn = -1;
+// if (type() == TICKS)
+ _lenTick = tempomap.frame2tick(len, &sn);
+ }
+
+//---------------------------------------------------------
+// lenTick
+//---------------------------------------------------------
+
+unsigned PosLen::lenTick() const
+ {
+ if (type() == FRAMES)
+ _lenTick = tempomap.frame2tick(_lenFrame, _lenTick, &sn);
+ return _lenTick;
+ }
+
+//---------------------------------------------------------
+// lenFrame
+//---------------------------------------------------------
+
+unsigned PosLen::lenFrame() const
+ {
+ if (type() == TICKS)
+ _lenFrame = tempomap.tick2frame(_lenTick, _lenFrame, &sn);
+ return _lenFrame;
+ }
+
+//---------------------------------------------------------
+// end
+//---------------------------------------------------------
+
+Pos PosLen::end() const
+ {
+ Pos pos(*this);
+ pos.invalidSn();
+ switch(type()) {
+ case FRAMES:
+ pos.setFrame(pos.frame() + _lenFrame);
+ break;
+ case TICKS:
+ pos.setTick(pos.tick() + _lenTick);
+ break;
+ }
+ return pos;
+ }
+
+//---------------------------------------------------------
+// setPos
+//---------------------------------------------------------
+
+void PosLen::setPos(const Pos& pos)
+ {
+ switch(pos.type()) {
+ case FRAMES:
+ setFrame(pos.frame());
+ break;
+ case TICKS:
+ setTick(pos.tick());
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// mbt
+//---------------------------------------------------------
+
+void Pos::mbt(int* bar, int* beat, int* tk) const
+ {
+ sigmap.tickValues(tick(), bar, beat, (unsigned*)tk);
+ }
+
+//---------------------------------------------------------
+// msf
+//---------------------------------------------------------
+
+void Pos::msf(int* min, int* sec, int* fr, int* subFrame) const
+ {
+ double time = double(frame()) / double(AL::sampleRate);
+ *min = int(time) / 60;
+ *sec = int(time) % 60;
+ double rest = time - (*min * 60 + *sec);
+ switch(AL::mtcType) {
+ case 0: // 24 frames sec
+ rest *= 24;
+ break;
+ case 1: // 25
+ rest *= 25;
+ break;
+ case 2: // 30 drop frame
+ rest *= 30;
+ break;
+ case 3: // 30 non drop frame
+ rest *= 30;
+ break;
+ }
+ *fr = int(rest);
+ *subFrame = int((rest- *fr)*100);
+ }
+
+//---------------------------------------------------------
+// timesig
+//---------------------------------------------------------
+
+TimeSignature Pos::timesig() const
+ {
+ return sigmap.timesig(tick());
+ }
+
+//---------------------------------------------------------
+// snap
+// raster = 1 no snap
+// raster = 0 snap to measure
+// all other raster values snap to raster tick
+//---------------------------------------------------------
+
+void Pos::snap(int raster)
+ {
+ setTick(sigmap.raster(tick(), raster));
+ }
+
+void Pos::upSnap(int raster)
+ {
+ setTick(sigmap.raster2(tick(), raster));
+ }
+
+void Pos::downSnap(int raster)
+ {
+ setTick(sigmap.raster1(tick(), raster));
+ }
+
+Pos Pos::snaped(int raster) const
+ {
+ return Pos(sigmap.raster(tick(), raster));
+ }
+
+Pos Pos::upSnaped(int raster) const
+ {
+ return Pos(sigmap.raster2(tick(), raster));
+ }
+
+Pos Pos::downSnaped(int raster) const
+ {
+ return Pos(sigmap.raster1(tick(), raster));
+ }
+}
+
diff --git a/muse/al/pos.h b/muse/al/pos.h
new file mode 100644
index 00000000..a771fc4b
--- /dev/null
+++ b/muse/al/pos.h
@@ -0,0 +1,128 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __POS_H__
+#define __POS_H__
+
+#include "sig.h"
+
+namespace AL {
+
+class Xml;
+
+enum TType { TICKS, FRAMES };
+
+//---------------------------------------------------------
+// Pos
+// depending on type _tick or _frame is a cached
+// value. When the tempomap changes, all cached values
+// are invalid. Sn is used to check for tempomap
+// changes.
+//---------------------------------------------------------
+
+class Pos {
+ public:
+
+ private:
+ TType _type;
+ mutable int sn;
+ mutable unsigned _tick;
+ mutable unsigned _frame;
+
+ public:
+ Pos();
+ Pos(const Pos&);
+ Pos(int measure, int beat, int tick);
+ Pos(int minute, int sec, int frame, int subframe);
+ Pos(unsigned, TType type = TICKS);
+ Pos(const QString&);
+ void dump(int n = 0) const;
+
+ unsigned time(TType t) const { return t == TICKS ? tick() : frame(); }
+ void mbt(int* measure, int* beat, int* tick) const;
+ void msf(int* minute, int* sec, int* frame, int* subframe) const;
+ TimeSignature timesig() const;
+ void snap(int);
+ void upSnap(int);
+ void downSnap(int);
+ Pos snaped(int) const;
+ Pos upSnaped(int) const;
+ Pos downSnaped(int) const;
+
+ void invalidSn() { sn = -1; }
+
+ TType type() const { return _type; }
+ void setType(TType t);
+
+ Pos& operator+=(const Pos& a);
+ Pos& operator+=(int a);
+ Pos& operator-=(const Pos& a);
+ Pos& operator-=(int a);
+
+ bool operator>=(const Pos& s) const;
+ bool operator>(const Pos& s) const;
+ bool operator<(const Pos& s) const;
+ bool operator<=(const Pos& s) const;
+ bool operator==(const Pos& s) const;
+ bool operator!=(const Pos& s) const;
+
+ friend Pos operator+(const Pos& a, const Pos& b);
+ friend Pos operator-(const Pos& a, const Pos& b);
+ friend Pos operator+(const Pos& a, int b);
+ friend Pos operator-(const Pos& a, int b);
+
+ unsigned tick() const;
+ unsigned frame() const;
+ void setTick(unsigned);
+ void setFrame(unsigned);
+
+ void write(Xml&, const char*) const;
+ void read(QDomNode);
+ bool isValid() const { return true; }
+ };
+
+//---------------------------------------------------------
+// PosLen
+//---------------------------------------------------------
+
+class PosLen : public Pos {
+ mutable unsigned _lenTick;
+ mutable unsigned _lenFrame;
+ mutable int sn;
+
+ public:
+ PosLen();
+ PosLen(const PosLen&);
+ void dump(int n = 0) const;
+
+ void write(Xml&, const char*) const;
+ void read(QDomNode);
+ void setLenTick(unsigned);
+ void setLenFrame(unsigned);
+ unsigned lenTick() const;
+ unsigned lenFrame() const;
+ Pos end() const;
+ unsigned endTick() const { return end().tick(); }
+ unsigned endFrame() const { return end().frame(); }
+ void setPos(const Pos&);
+ };
+}
+
+#endif
diff --git a/muse/al/sig.cpp b/muse/al/sig.cpp
new file mode 100644
index 00000000..345cd43e
--- /dev/null
+++ b/muse/al/sig.cpp
@@ -0,0 +1,407 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al.h"
+#include "sig.h"
+#include "xml.h"
+
+namespace AL {
+
+SigList sigmap;
+
+//---------------------------------------------------------
+// SigList
+//---------------------------------------------------------
+
+SigList::SigList()
+ {
+ insert(std::pair<const unsigned, SigEvent*> (MAX_TICK, new SigEvent(TimeSignature(4, 4), 0)));
+ }
+
+//---------------------------------------------------------
+// add
+// signatures are only allowed at the beginning of
+// a bar
+//---------------------------------------------------------
+
+void SigList::add(unsigned tick, const TimeSignature& s)
+ {
+ if (s.z == 0 || s.n == 0) {
+ printf("illegal signature %d/%d\n", s.z, s.n);
+ }
+ tick = raster1(tick, 0);
+ iSigEvent e = upper_bound(tick);
+
+ if (tick == e->second->tick) {
+ e->second->sig = s;
+ }
+ else {
+ SigEvent* ne = e->second;
+ SigEvent* ev = new SigEvent(ne->sig, ne->tick);
+ ne->sig = s;
+ ne->tick = tick;
+ insert(std::pair<const unsigned, SigEvent*> (tick, ev));
+ }
+ normalize();
+ }
+
+//---------------------------------------------------------
+// del
+//---------------------------------------------------------
+
+void SigList::del(unsigned tick)
+ {
+// printf("SigList::del(%d)\n", tick);
+ iSigEvent e = find(tick);
+ if (e == end()) {
+ printf("SigList::del(%d): not found\n", tick);
+ return;
+ }
+ iSigEvent ne = e;
+ ++ne;
+ if (ne == end()) {
+ printf("SigList::del() HALLO\n");
+ return;
+ }
+ ne->second->sig = e->second->sig;
+ ne->second->tick = e->second->tick;
+ erase(e);
+ normalize();
+ }
+
+//---------------------------------------------------------
+// SigList::normalize
+//---------------------------------------------------------
+
+void SigList::normalize()
+ {
+ TimeSignature sig(0, 0);
+ unsigned tick = 0;
+ iSigEvent ee;
+
+ for (iSigEvent e = begin(); e != end();) {
+ if (sig.z == e->second->sig.z && sig.n == e->second->sig.n) {
+ e->second->tick = tick;
+ erase(ee);
+ }
+ sig = e->second->sig;
+ ee = e;
+ tick = e->second->tick;
+ ++e;
+ }
+
+ int bar = 0;
+ for (iSigEvent e = begin(); e != end();) {
+ e->second->bar = bar;
+ int delta = e->first - e->second->tick;
+ int ticksB = ticks_beat(e->second->sig.n);
+ int ticksM = ticksB * e->second->sig.z;
+ bar += delta / ticksM;
+ if (delta % ticksM) // Teil eines Taktes
+ ++bar;
+ ++e;
+ }
+ }
+
+//---------------------------------------------------------
+// SigList::dump
+//---------------------------------------------------------
+
+void SigList::dump() const
+ {
+ printf("\nSigList:\n");
+ for (ciSigEvent i = begin(); i != end(); ++i) {
+ printf("%6d %06d Bar %3d %02d/%d\n",
+ i->first, i->second->tick,
+ i->second->bar, i->second->sig.z, i->second->sig.n);
+ }
+ }
+
+void SigList::clear()
+ {
+ for (iSigEvent i = begin(); i != end(); ++i)
+ delete i->second;
+ SIGLIST::clear();
+ insert(std::pair<const unsigned, SigEvent*> (MAX_TICK, new SigEvent(TimeSignature(4, 4), 0)));
+ }
+
+//---------------------------------------------------------
+// ticksMeasure
+//---------------------------------------------------------
+
+int SigList::ticksMeasure(const TimeSignature& sig) const
+ {
+ return ticks_beat(sig.n) * sig.z;
+ }
+
+int SigList::ticksMeasure(unsigned tick) const
+ {
+ ciSigEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("ticksMeasure: not found %d\n", tick);
+ // abort();
+ return 0;
+ }
+ return ticksMeasure(i->second->sig);
+ }
+
+//---------------------------------------------------------
+// ticksBeat
+//---------------------------------------------------------
+
+int SigList::ticksBeat(unsigned tick) const
+ {
+ ciSigEvent i = upper_bound(tick);
+ return ticks_beat(i->second->sig.n);
+ }
+
+int SigList::ticks_beat(int n) const
+ {
+ int m = AL::division;
+ switch (n) {
+ case 1: m <<= 2; break; // 1536
+ case 2: m <<= 1; break; // 768
+ case 3: m += m >> 1; break; // 384+192
+ case 4: break; // 384
+ case 8: m >>= 1; break; // 192
+ case 16: m >>= 2; break; // 96
+ case 32: m >>= 3; break; // 48
+ case 64: m >>= 4; break; // 24
+ case 128: m >>= 5; break; // 12
+ default: break;
+ }
+ return m;
+ }
+
+//---------------------------------------------------------
+// timesig
+//---------------------------------------------------------
+
+TimeSignature SigList::timesig(unsigned tick) const
+ {
+ ciSigEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("timesig(%d): not found\n", tick);
+ // abort();
+ return TimeSignature(4,4);
+ }
+ return i->second->sig;
+ }
+
+//---------------------------------------------------------
+// tickValues
+//---------------------------------------------------------
+
+void SigList::tickValues(unsigned t, int* bar, int* beat, unsigned* tick) const
+ {
+ ciSigEvent e = upper_bound(t);
+ if (e == end()) {
+ fprintf(stderr, "tickValues(0x%x) not found(%d)\n", t, size());
+//DEBUG
+// abort();
+ *bar = 0;
+ *beat = 0;
+ *tick = 0;
+ return;
+ }
+
+ int delta = t - e->second->tick;
+ int ticksB = ticks_beat(e->second->sig.n);
+ int ticksM = ticksB * e->second->sig.z;
+ *bar = e->second->bar + delta / ticksM;
+ int rest = delta % ticksM;
+ *beat = rest / ticksB;
+ *tick = rest % ticksB;
+ }
+
+//---------------------------------------------------------
+// bar2tick
+//---------------------------------------------------------
+
+unsigned SigList::bar2tick(int bar, int beat, unsigned tick) const
+ {
+ ciSigEvent e;
+
+ if (bar < 0)
+ bar = 0;
+ for (e = begin(); e != end();) {
+ ciSigEvent ee = e;
+ ++ee;
+ if (ee == end())
+ break;
+ if (bar < ee->second->bar)
+ break;
+ e = ee;
+ }
+ int ticksB = ticks_beat(e->second->sig.n);
+ int ticksM = ticksB * e->second->sig.z;
+ return e->second->tick + (bar-e->second->bar)*ticksM + ticksB*beat + tick;
+ }
+
+//---------------------------------------------------------
+// raster
+//---------------------------------------------------------
+
+unsigned SigList::raster(unsigned t, int raster) const
+ {
+ if (raster == 1)
+ return t;
+ ciSigEvent e = upper_bound(t);
+ if (e == end()) {
+ printf("SigList::raster(%x,)\n", t);
+ // abort();
+ return t;
+ }
+ int delta = t - e->second->tick;
+ int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
+ if (raster == 0)
+ raster = ticksM;
+ int rest = delta % ticksM;
+ int bb = (delta/ticksM)*ticksM;
+ return e->second->tick + bb + ((rest + raster/2)/raster)*raster;
+ }
+
+//---------------------------------------------------------
+// raster1
+// round down
+//---------------------------------------------------------
+
+unsigned SigList::raster1(unsigned t, int raster) const
+ {
+ if (raster == 1)
+ return t;
+ ciSigEvent e = upper_bound(t);
+
+ int delta = t - e->second->tick;
+ int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
+ if (raster == 0)
+ raster = ticksM;
+ int rest = delta % ticksM;
+ int bb = (delta/ticksM)*ticksM;
+ return e->second->tick + bb + (rest/raster)*raster;
+ }
+
+//---------------------------------------------------------
+// raster2
+// round up
+//---------------------------------------------------------
+
+unsigned SigList::raster2(unsigned t, int raster) const
+ {
+ if (raster == 1)
+ return t;
+ ciSigEvent e = upper_bound(t);
+
+ int delta = t - e->second->tick;
+ int ticksM = ticks_beat(e->second->sig.n) * e->second->sig.z;
+ if (raster == 0)
+ raster = ticksM;
+ int rest = delta % ticksM;
+ int bb = (delta/ticksM)*ticksM;
+ return e->second->tick + bb + ((rest+raster-1)/raster)*raster;
+ }
+
+//---------------------------------------------------------
+// rasterStep
+//---------------------------------------------------------
+
+int SigList::rasterStep(unsigned t, int raster) const
+ {
+ if (raster == 0) {
+ ciSigEvent e = upper_bound(t);
+ return ticks_beat(e->second->sig.n) * e->second->sig.z;
+ }
+ return raster;
+ }
+
+//---------------------------------------------------------
+// SigList::write
+//---------------------------------------------------------
+
+void SigList::write(Xml& xml) const
+ {
+ xml.tag("siglist");
+ for (ciSigEvent i = begin(); i != end(); ++i)
+ i->second->write(xml, i->first);
+ xml.etag("siglist");
+ }
+
+//---------------------------------------------------------
+// SigList::read
+//---------------------------------------------------------
+
+void SigList::read(QDomNode node)
+ {
+ while (!node.isNull()) {
+ QDomElement e = node.toElement();
+ if (e.tagName() == "sig") {
+ SigEvent* t = new SigEvent();
+ unsigned tick = t->read(node);
+ iSigEvent pos = find(tick);
+ if (pos != end())
+ erase(pos);
+ insert(std::pair<const unsigned, SigEvent*> (tick, t));
+ }
+ else
+ printf("MusE:SigList: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ normalize();
+ }
+
+//---------------------------------------------------------
+// SigEvent::write
+//---------------------------------------------------------
+
+void SigEvent::write(Xml& xml, int at) const
+ {
+ xml.tag("sig at=\"%d\"", at);
+ xml.intTag("tick", tick);
+ xml.intTag("nom", sig.z);
+ xml.intTag("denom", sig.n);
+ xml.etag("sig");
+ }
+
+//---------------------------------------------------------
+// SigEvent::read
+//---------------------------------------------------------
+
+int SigEvent::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ int at = e.attribute("at", "0").toInt();
+ node = node.firstChild();
+
+ while (!node.isNull()) {
+ QDomElement e = node.toElement();
+ if (e.tagName() == "tick")
+ tick = e.text().toInt();
+ else if (e.tagName() == "nom")
+ sig.z = e.text().toInt();
+ else if (e.tagName() == "denom")
+ sig.n = e.text().toInt();
+ else
+ printf("MusE:SigEvent: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ return at;
+ }
+
+}
diff --git a/muse/al/sig.h b/muse/al/sig.h
new file mode 100644
index 00000000..d0c70410
--- /dev/null
+++ b/muse/al/sig.h
@@ -0,0 +1,103 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __SIG_H__
+#define __SIG_H__
+
+namespace AL {
+
+#ifndef MAX_TICK
+#define MAX_TICK (0x7fffffff/100)
+#endif
+
+class Xml;
+
+//---------------------------------------------------------
+// TimeSignature
+//---------------------------------------------------------
+
+struct TimeSignature {
+ int z, n;
+ TimeSignature() { z = 4; n = 4; }
+ TimeSignature(int a, int b) { z = a; n = b; }
+ };
+
+//---------------------------------------------------------
+// Signature Event
+//---------------------------------------------------------
+
+struct SigEvent {
+ TimeSignature sig;
+ unsigned tick; // signature valid from this position
+ int bar; // precomputed
+
+ int read(QDomNode);
+ void write(Xml&, int) const;
+
+ SigEvent() { }
+ SigEvent(const TimeSignature& s, unsigned tk) {
+ sig = s;
+ tick = tk;
+ bar = 0;
+ }
+ };
+
+//---------------------------------------------------------
+// SigList
+//---------------------------------------------------------
+
+typedef std::map<unsigned, SigEvent*, std::less<unsigned> > SIGLIST;
+typedef SIGLIST::iterator iSigEvent;
+typedef SIGLIST::const_iterator ciSigEvent;
+typedef SIGLIST::reverse_iterator riSigEvent;
+typedef SIGLIST::const_reverse_iterator criSigEvent;
+
+class SigList : public SIGLIST {
+ int ticks_beat(int N) const;
+ void normalize();
+ int ticksMeasure(const TimeSignature&) const;
+
+ public:
+ SigList();
+ void clear();
+ void add(unsigned tick, const TimeSignature& s);
+ void del(unsigned tick);
+
+ void read(QDomNode);
+ void write(Xml&) const;
+ void dump() const;
+
+ TimeSignature timesig(unsigned tick) const;
+ void tickValues(unsigned t, int* bar, int* beat, unsigned* tick) const;
+ unsigned bar2tick(int bar, int beat, unsigned tick) const;
+
+ int ticksMeasure(unsigned tick) const;
+ int ticksBeat(unsigned tick) const;
+ unsigned raster(unsigned tick, int raster) const;
+ unsigned raster1(unsigned tick, int raster) const; // round down
+ unsigned raster2(unsigned tick, int raster) const; // round up
+ int rasterStep(unsigned tick, int raster) const;
+ };
+
+extern SigList sigmap;
+
+}
+
+#endif
diff --git a/muse/al/tempo.cpp b/muse/al/tempo.cpp
new file mode 100644
index 00000000..9a64f3e8
--- /dev/null
+++ b/muse/al/tempo.cpp
@@ -0,0 +1,393 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al.h"
+#include "tempo.h"
+#include "xml.h"
+
+namespace AL {
+
+TempoList tempomap;
+
+//---------------------------------------------------------
+// TempoList
+//---------------------------------------------------------
+
+TempoList::TempoList()
+ {
+ _tempo = 500000;
+ insert(std::pair<const unsigned, TEvent*> (MAX_TICK+1, new TEvent(_tempo, 0)));
+ _tempoSN = 1;
+ _globalTempo = 100;
+ useList = true;
+ }
+
+//---------------------------------------------------------
+// add
+//---------------------------------------------------------
+
+void TempoList::add(unsigned tick, int tempo)
+ {
+ if (tick > MAX_TICK)
+ tick = MAX_TICK;
+
+ iTEvent e = upper_bound(tick);
+
+ if (tick == e->second->tick)
+ e->second->tempo = tempo;
+ else {
+ TEvent* ne = e->second;
+ TEvent* ev = new TEvent(ne->tempo, ne->tick);
+ ne->tempo = tempo;
+ ne->tick = tick;
+ insert(std::pair<const unsigned, TEvent*> (tick, ev));
+ }
+ normalize();
+ }
+
+//---------------------------------------------------------
+// TempoList::normalize
+//---------------------------------------------------------
+
+void TempoList::normalize()
+ {
+ int frame = 0;
+ for (iTEvent e = begin(); e != end(); ++e) {
+ e->second->frame = frame;
+ unsigned dtick = e->first - e->second->tick;
+ double dtime = double(dtick) / (division * _globalTempo * 10000.0/e->second->tempo);
+ frame += lrint(dtime * sampleRate);
+ }
+ }
+
+//---------------------------------------------------------
+// TempoList::dump
+//---------------------------------------------------------
+
+void TempoList::dump() const
+ {
+ printf("\nTempoList:\n");
+ for (ciTEvent i = begin(); i != end(); ++i) {
+ printf("%6d %06d Tempo %6d Frame %d\n",
+ i->first, i->second->tick, i->second->tempo,
+ i->second->frame);
+ }
+ }
+
+//---------------------------------------------------------
+// clear
+//---------------------------------------------------------
+
+void TempoList::clear()
+ {
+ for (iTEvent i = begin(); i != end(); ++i)
+ delete i->second;
+ TEMPOLIST::clear();
+ insert(std::pair<const unsigned, TEvent*> (MAX_TICK+1, new TEvent(500000, 0)));
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// tempo
+//---------------------------------------------------------
+
+int TempoList::tempo(unsigned tick) const
+ {
+ if (useList) {
+ ciTEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("no TEMPO at tick %d,0x%x\n", tick, tick);
+ return 1000;
+ }
+ return i->second->tempo;
+ }
+ else
+ return _tempo;
+ }
+
+//---------------------------------------------------------
+// del
+//---------------------------------------------------------
+
+void TempoList::del(unsigned tick)
+ {
+// printf("TempoList::del(%d)\n", tick);
+ iTEvent e = find(tick);
+ if (e == end()) {
+ printf("TempoList::del(%d): not found\n", tick);
+ return;
+ }
+ del(e);
+ ++_tempoSN;
+ }
+
+void TempoList::del(iTEvent e)
+ {
+ iTEvent ne = e;
+ ++ne;
+ if (ne == end()) {
+ printf("TempoList::del(): not found\n");
+ return;
+ }
+ ne->second->tempo = e->second->tempo;
+ ne->second->tick = e->second->tick;
+ erase(e);
+ normalize();
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// change
+//---------------------------------------------------------
+
+void TempoList::change(unsigned tick, int newTempo)
+ {
+ iTEvent e = find(tick);
+ e->second->tempo = newTempo;
+ normalize();
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// setTempo
+// called from transport window
+// & slave mode tempo changes
+//---------------------------------------------------------
+
+void TempoList::setTempo(unsigned tick, int newTempo)
+ {
+ if (useList)
+ add(tick, newTempo);
+ else
+ _tempo = newTempo;
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// setGlobalTempo
+//---------------------------------------------------------
+
+void TempoList::setGlobalTempo(int val)
+ {
+ _globalTempo = val;
+ ++_tempoSN;
+ normalize();
+ }
+
+//---------------------------------------------------------
+// addTempo
+//---------------------------------------------------------
+
+void TempoList::addTempo(unsigned t, int tempo)
+ {
+ add(t, tempo);
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// delTempo
+//---------------------------------------------------------
+
+void TempoList::delTempo(unsigned tick)
+ {
+ del(tick);
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// changeTempo
+//---------------------------------------------------------
+
+void TempoList::changeTempo(unsigned tick, int newTempo)
+ {
+ change(tick, newTempo);
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// setMasterFlag
+//---------------------------------------------------------
+
+bool TempoList::setMasterFlag(unsigned /*tick*/, bool val)
+ {
+ if (useList != val) {
+ useList = val;
+ ++_tempoSN;
+ return true;
+ }
+ return false;
+ }
+
+//---------------------------------------------------------
+// tick2frame
+//---------------------------------------------------------
+
+unsigned TempoList::tick2frame(unsigned tick, unsigned frame, int* sn) const
+ {
+ return (*sn == _tempoSN) ? frame : tick2frame(tick, sn);
+ }
+
+//---------------------------------------------------------
+// tick2frame
+//---------------------------------------------------------
+
+unsigned TempoList::tick2frame(unsigned tick, int* sn) const
+ {
+ int f;
+ if (useList) {
+ ciTEvent i = upper_bound(tick);
+ if (i == end()) {
+ printf("tick2frame(%d,0x%x): not found\n", tick, tick);
+ abort(); // debug
+ return 0;
+ }
+ unsigned dtick = tick - i->second->tick;
+ double dtime = double(dtick) / (division * _globalTempo * 10000.0/ i->second->tempo);
+ unsigned dframe = lrint(dtime * sampleRate);
+ f = i->second->frame + dframe;
+ }
+ else {
+ double t = (double(tick) * double(_tempo)) / (double(division) * _globalTempo * 10000.0);
+ f = lrint(t * sampleRate);
+ }
+ if (sn)
+ *sn = _tempoSN;
+ return f;
+ }
+
+//---------------------------------------------------------
+// frame2tick
+// return cached value t if list did not change
+//---------------------------------------------------------
+
+unsigned TempoList::frame2tick(unsigned frame, unsigned t, int* sn) const
+ {
+ return (*sn == _tempoSN) ? t : frame2tick(frame, sn);
+ }
+
+//---------------------------------------------------------
+// frame2tick
+//---------------------------------------------------------
+
+unsigned TempoList::frame2tick(unsigned frame, int* sn) const
+ {
+ unsigned tick;
+ if (useList) {
+ ciTEvent e;
+ for (e = begin(); e != end();) {
+ ciTEvent ee = e;
+ ++ee;
+ if (ee == end())
+ break;
+ if (frame < ee->second->frame)
+ break;
+ e = ee;
+ }
+ unsigned te = e->second->tempo;
+ int dframe = frame - e->second->frame;
+ double dtime = double(dframe) / double(sampleRate);
+ tick = e->second->tick + lrint(dtime * _globalTempo * division * 10000.0 / te);
+ }
+ else
+ tick = lrint((double(frame)/double(sampleRate)) * _globalTempo * division * 10000.0 / double(_tempo));
+ if (sn)
+ *sn = _tempoSN;
+ return tick;
+ }
+
+//---------------------------------------------------------
+// TempoList::write
+//---------------------------------------------------------
+
+void TempoList::write(Xml& xml) const
+ {
+ xml.tag("tempolist fix=\"%d\"", _tempo);
+ if (_globalTempo != 100)
+ xml.intTag("globalTempo", _globalTempo);
+ for (ciTEvent i = begin(); i != end(); ++i)
+ i->second->write(xml, i->first);
+ xml.etag("tempolist");
+ }
+
+//---------------------------------------------------------
+// TempoList::read
+//---------------------------------------------------------
+
+void TempoList::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ _tempo = e.attribute("fix","500000").toInt();
+
+ node = node.firstChild();
+ while (!node.isNull()) {
+ e = node.toElement();
+ if (e.tagName() == "tempo") {
+ TEvent* t = new TEvent();
+ unsigned tick = t->read(node);
+ iTEvent pos = find(tick);
+ if (pos != end())
+ erase(pos);
+ insert(std::pair<const int, TEvent*> (tick, t));
+ }
+ else if (e.tagName() == "globalTempo")
+ _globalTempo = e.text().toInt();
+ else
+ printf("MusE:Tempolist: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ normalize();
+ ++_tempoSN;
+ }
+
+//---------------------------------------------------------
+// TEvent::write
+//---------------------------------------------------------
+
+void TEvent::write(Xml& xml, int at) const
+ {
+ xml.tag("tempo at=\"%d\"", at);
+ xml.intTag("tick", tick);
+ xml.intTag("val", tempo);
+ xml.etag("tempo");
+ }
+
+//---------------------------------------------------------
+// TEvent::read
+//---------------------------------------------------------
+
+int TEvent::read(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ int at = e.attribute("at","0").toInt();
+
+ node = node.firstChild();
+ while (!node.isNull()) {
+ e = node.toElement();
+ if (e.tagName() == "tick")
+ tick = e.text().toInt();
+ else if (e.tagName() == "val")
+ tempo = e.text().toInt();
+ else
+ printf("MusE:TEvent: unknown tag %s\n", e.tagName().toLatin1().data());
+ node = node.nextSibling();
+ }
+ return at;
+ }
+}
diff --git a/muse/al/tempo.h b/muse/al/tempo.h
new file mode 100644
index 00000000..68dcbb14
--- /dev/null
+++ b/muse/al/tempo.h
@@ -0,0 +1,100 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __TEMPO_H__
+#define __TEMPO_H__
+
+namespace AL {
+
+#ifndef MAX_TICK
+#define MAX_TICK (0x7fffffff/100)
+#endif
+
+class Xml;
+
+//---------------------------------------------------------
+// Tempo Event
+//---------------------------------------------------------
+
+struct TEvent {
+ int tempo;
+ unsigned tick; // new tempo at tick
+ unsigned frame; // precomputed time for tick in sec
+
+ int read(QDomNode);
+ void write(Xml&, int) const;
+
+ TEvent() { }
+ TEvent(unsigned t, unsigned tk) {
+ tempo = t;
+ tick = tk;
+ frame = 0;
+ }
+ };
+
+//---------------------------------------------------------
+// TempoList
+//---------------------------------------------------------
+
+typedef std::map<unsigned, TEvent*, std::less<unsigned> > TEMPOLIST;
+typedef TEMPOLIST::iterator iTEvent;
+typedef TEMPOLIST::const_iterator ciTEvent;
+typedef TEMPOLIST::reverse_iterator riTEvent;
+typedef TEMPOLIST::const_reverse_iterator criTEvent;
+
+class TempoList : public TEMPOLIST {
+ int _tempoSN; // serial no to track tempo changes
+ bool useList;
+ int _tempo; // tempo if not using tempo list
+ int _globalTempo; // %percent 50-200%
+
+ void normalize();
+ void add(unsigned tick, int tempo);
+ void change(unsigned tick, int newTempo);
+ void del(iTEvent);
+ void del(unsigned tick);
+
+ public:
+ TempoList();
+ void clear();
+
+ void read(QDomNode);
+ void write(Xml&) const;
+ void dump() const;
+
+ int tempo(unsigned tick) const;
+ unsigned tick2frame(unsigned tick, unsigned frame, int* sn) const;
+ unsigned tick2frame(unsigned tick, int* sn = 0) const;
+ unsigned frame2tick(unsigned frame, int* sn = 0) const;
+ unsigned frame2tick(unsigned frame, unsigned tick, int* sn) const;
+ int tempoSN() const { return _tempoSN; }
+ void setTempo(unsigned tick, int newTempo);
+ void addTempo(unsigned t, int tempo);
+ void delTempo(unsigned tick);
+ void changeTempo(unsigned tick, int newTempo);
+ bool setMasterFlag(unsigned tick, bool val);
+ int globalTempo() const { return _globalTempo; }
+ void setGlobalTempo(int val);
+ };
+
+extern TempoList tempomap;
+}
+
+#endif
diff --git a/muse/al/xml.cpp b/muse/al/xml.cpp
new file mode 100644
index 00000000..616b474c
--- /dev/null
+++ b/muse/al/xml.cpp
@@ -0,0 +1,344 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "xml.h"
+
+
+namespace AL {
+
+//---------------------------------------------------------
+// Xml
+//---------------------------------------------------------
+
+Xml::Xml(QIODevice* device)
+ : QTextStream(device)
+ {
+ level = 0;
+ }
+
+//---------------------------------------------------------
+// header
+//---------------------------------------------------------
+
+void Xml::header()
+ {
+ *this << "<?xml version=\"1.0\"?>\n";
+ }
+
+//---------------------------------------------------------
+// put
+//---------------------------------------------------------
+
+void Xml::put(const char* format, ...)
+ {
+ va_list args;
+ va_start(args, format);
+ putLevel();
+ vsnprintf(buffer, BS, format, args);
+ va_end(args);
+ *this << buffer;
+ *this << '\n';
+ }
+
+//---------------------------------------------------------
+// nput
+//---------------------------------------------------------
+
+void Xml::nput(const char* format, ...)
+ {
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, BS, format, args);
+ *this << buffer;
+ va_end(args);
+ }
+
+//---------------------------------------------------------
+// tdata
+//---------------------------------------------------------
+
+void Xml::tdata(const QString& s)
+ {
+ putLevel();
+ *this << s << endl;
+ }
+
+//---------------------------------------------------------
+// tag
+//---------------------------------------------------------
+
+void Xml::tag(const char* format, ...)
+ {
+ va_list args;
+ va_start(args, format);
+ putLevel();
+ *this << '<';
+ vsnprintf(buffer, BS, format, args);
+ *this << buffer;
+ va_end(args);
+ *this << '>' << endl;
+ ++level;
+ }
+
+void Xml::tagE(const char* format, ...)
+ {
+ va_list args;
+ va_start(args, format);
+ putLevel();
+ *this << '<';
+ vsnprintf(buffer, BS, format, args);
+ *this << buffer;
+ va_end(args);
+ *this << "/>" << endl;
+ }
+
+//---------------------------------------------------------
+// etag
+//---------------------------------------------------------
+
+void Xml::etag(const char* format, ...)
+ {
+ va_list args;
+ va_start(args, format);
+ putLevel();
+ *this << "</";
+ vsnprintf(buffer, BS, format, args);
+ *this << buffer;
+ va_end(args);
+ *this << '>' << endl;
+ --level;
+ }
+
+void Xml::putLevel()
+ {
+ for (int i = 0; i < level*2; ++i)
+ *this << ' ';
+ }
+
+void Xml::intTag(const char* name, int val)
+ {
+ putLevel();
+ *this << "<" << name << ">" << val << "</" << name << ">\n";
+ }
+
+void Xml::floatTag(const char* name, float val)
+ {
+ putLevel();
+ *this << QString("<%1>%2</%3>\n").arg(name).arg(val).arg(name);
+ }
+
+void Xml::doubleTag(const char* name, double val)
+ {
+ putLevel();
+ QString s("<%1>%2</%3>\n");
+ *this << s.arg(name).arg(val).arg(name);
+ }
+
+void Xml::strTag(const char* name, const char* val)
+ {
+ putLevel();
+ *this << "<" << name << ">";
+ if (val) {
+ while (*val) {
+ switch(*val) {
+ case '&':
+ *this << "&amp;";
+ break;
+ case '<':
+ *this << "&lt;";
+ break;
+ case '>':
+ *this << "&gt;";
+ break;
+ case '"':
+ *this << "&quot;";
+ break;
+ case '\'':
+ *this << "&apos;";
+ break;
+ default:
+ *this << *val;
+ break;
+ }
+ ++val;
+ }
+ }
+ *this << "</" << name << ">\n";
+ }
+
+//---------------------------------------------------------
+// colorTag
+//---------------------------------------------------------
+
+void Xml::colorTag(const char* name, const QColor& color)
+ {
+ putLevel();
+ snprintf(buffer, BS, "<%s r=\"%d\" g=\"%d\" b=\"%d\" />\n",
+ name, color.red(), color.green(), color.blue());
+ *this << buffer;
+ }
+
+//---------------------------------------------------------
+// geometryTag
+//---------------------------------------------------------
+
+void Xml::geometryTag(const char* name, const QWidget* g)
+ {
+ qrectTag(name, QRect(g->pos(), g->size()));
+ }
+
+//---------------------------------------------------------
+// qrectTag
+//---------------------------------------------------------
+
+void Xml::qrectTag(const char* name, const QRect& r)
+ {
+ putLevel();
+ *this << "<" << name;
+ snprintf(buffer, BS, " x=\"%d\" y=\"%d\" w=\"%d\" h=\"%d\" />\n",
+ r.x(), r.y(), r.width(), r.height());
+ *this << buffer;
+ }
+
+//---------------------------------------------------------
+// strTag
+//---------------------------------------------------------
+
+void Xml::strTag(const char* name, const QString& val)
+ {
+ strTag(name, val.toLatin1().data());
+ }
+
+//---------------------------------------------------------
+// readGeometry
+//---------------------------------------------------------
+
+QRect readGeometry(QDomNode node)
+ {
+ QDomElement e = node.toElement();
+ int x = e.attribute("x","0").toInt();
+ int y = e.attribute("y","0").toInt();
+ int w = e.attribute("w","50").toInt();
+ int h = e.attribute("h","50").toInt();
+ return QRect(x, y, w, h);
+ }
+
+//---------------------------------------------------------
+// writeProperties
+//---------------------------------------------------------
+
+void Xml::writeProperties(const QObject* o)
+ {
+ const QMetaObject* meta = o->metaObject();
+
+ //
+ // start from dummy "muse" property, assuming this is the
+ // first muse propertie in widget hierarchy
+ //
+ int from = meta->indexOfProperty("muse") + 1;
+ int n = meta->propertyCount();
+ for (int i = from; i < n; ++i) {
+ QMetaProperty p = meta->property(i);
+ if (!p.isScriptable())
+ continue;
+ const char* name = p.name();
+ QVariant v = p.read(o);
+ switch(v.type()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ intTag(name, v.toInt());
+ break;
+ case QVariant::Double:
+ doubleTag(name, v.toDouble());
+ break;
+ case QVariant::String:
+ strTag(name, v.toString());
+ break;
+ case QVariant::Rect:
+ qrectTag(name, v.toRect());
+ break;
+ case QVariant::Point:
+ {
+ QPoint p = v.toPoint();
+ putLevel();
+ *this << "<" << name;
+ snprintf(buffer, BS, " x=\"%d\" y=\"%d\" />\n",
+ p.x(), p.y());
+ *this << buffer;
+ }
+ break;
+
+ default:
+ printf("MusE:%s type %d not implemented\n",
+ meta->className(), v.type());
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// readProperties
+//---------------------------------------------------------
+
+void readProperties(QObject* o, QDomNode node)
+ {
+ const QMetaObject* meta = o->metaObject();
+
+ QDomElement e = node.toElement();
+ QString tag(e.tagName());
+ int idx = meta->indexOfProperty(tag.toLatin1().data());
+ if (idx == -1) {
+ printf("MusE:%s: unknown tag %s\n",
+ meta->className(), tag.toLatin1().data());
+ return;
+ }
+ QMetaProperty p = meta->property(idx);
+ QVariant v;
+ switch(p.type()) {
+ case QVariant::Int:
+ case QVariant::Bool:
+ v.setValue(e.text().toInt());
+ break;
+ case QVariant::Double:
+ v.setValue(e.text().toDouble());
+ break;
+ case QVariant::String:
+ v.setValue(e.text());
+ break;
+ case QVariant::Rect:
+ v.setValue(AL::readGeometry(node));
+ break;
+ case QVariant::Point:
+ {
+ int x = e.attribute("x","0").toInt();
+ int y = e.attribute("y","0").toInt();
+ v.setValue(QPoint(x, y));
+ }
+ break;
+ default:
+ printf("MusE:%s type %d not implemented\n",
+ meta->className(), p.type());
+ return;
+ }
+ if (p.isWritable())
+ p.write(o, v);
+ }
+}
+
diff --git a/muse/al/xml.h b/muse/al/xml.h
new file mode 100644
index 00000000..4c438c3b
--- /dev/null
+++ b/muse/al/xml.h
@@ -0,0 +1,62 @@
+//=============================================================================
+// AL
+// Audio Utility Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __XML_H__
+#define __XML_H__
+
+namespace AL {
+
+static const int BS = 2048;
+
+//---------------------------------------------------------
+// Xml
+//---------------------------------------------------------
+
+class Xml : public QTextStream {
+ char buffer[BS];
+ int level;
+
+ public:
+ Xml(QIODevice*);
+ void header();
+ void putLevel();
+ void put(const char* format, ...);
+ void nput(const char* format, ...);
+ void tag(const char* format, ...);
+ void etag(const char* format, ...);
+ void tagE(const char* format, ...);
+ void tdata(const QString&);
+ void intTag(const char* const name, int val);
+ void doubleTag(const char* const name, double val);
+ void floatTag(const char* const name, float val);
+ void strTag(const char* const name, const char* val);
+ void strTag(const char* const name, const QString& s);
+ void colorTag(const char* name, const QColor& color);
+ void geometryTag(const char* name, const QWidget* g);
+ void qrectTag(const char* name, const QRect& r);
+ void writeProperties(const QObject*);
+ };
+
+extern QRect readGeometry(QDomNode);
+extern void readProperties(QObject* o, QDomNode node);
+}
+
+#endif
+