diff options
| author | Werner Schweer <ws.seh.de> | 2006-05-03 12:42:25 +0000 |
|---|---|---|
| committer | Werner Schweer <ws.seh.de> | 2006-05-03 12:42:25 +0000 |
| commit | b125dd455e563bf098d8d59d20202985b76103a9 (patch) | |
| tree | 6cb0785cba4966ed46a3a6a8891ce5098a7e151a /muse/al | |
initial import
Diffstat (limited to 'muse/al')
| -rw-r--r-- | muse/al/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | muse/al/al.cpp | 28 | ||||
| -rw-r--r-- | muse/al/al.h | 33 | ||||
| -rw-r--r-- | muse/al/marker.cpp | 86 | ||||
| -rw-r--r-- | muse/al/marker.h | 67 | ||||
| -rw-r--r-- | muse/al/pos.cpp | 581 | ||||
| -rw-r--r-- | muse/al/pos.h | 128 | ||||
| -rw-r--r-- | muse/al/sig.cpp | 407 | ||||
| -rw-r--r-- | muse/al/sig.h | 103 | ||||
| -rw-r--r-- | muse/al/tempo.cpp | 393 | ||||
| -rw-r--r-- | muse/al/tempo.h | 100 | ||||
| -rw-r--r-- | muse/al/xml.cpp | 344 | ||||
| -rw-r--r-- | muse/al/xml.h | 62 |
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 << "&"; + break; + case '<': + *this << "<"; + break; + case '>': + *this << ">"; + break; + case '"': + *this << """; + break; + case '\'': + *this << "'"; + 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 + |
