605 lines
15 KiB
C++
605 lines
15 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
//
|
|
// Copyright (C) 2002-2009 Werner Schweer
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2
|
|
// as published by the Free Software Foundation and appearing in
|
|
// the file LICENCE.GPL
|
|
//=============================================================================
|
|
|
|
#include "pos.h"
|
|
#include "xml.h"
|
|
#include "sig.h"
|
|
#include "tempo.h"
|
|
|
|
namespace Ms {
|
|
|
|
//---------------------------------------------------------
|
|
// Pos
|
|
//---------------------------------------------------------
|
|
|
|
Pos::Pos()
|
|
{
|
|
tempo = 0;
|
|
sig = 0;
|
|
_type = TType::TICKS;
|
|
_tick = 0;
|
|
_frame = 0;
|
|
sn = -1;
|
|
_valid = false;
|
|
}
|
|
|
|
Pos::Pos(TempoMap* tl, TimeSigMap* sl)
|
|
{
|
|
tempo = tl;
|
|
sig = sl;
|
|
_type = TType::TICKS;
|
|
_tick = 0;
|
|
_frame = 0;
|
|
sn = -1;
|
|
_valid = false;
|
|
}
|
|
|
|
Pos::Pos(TempoMap* tl, TimeSigMap* sl, unsigned t, TType timeType)
|
|
{
|
|
tempo = tl;
|
|
sig = sl;
|
|
_type = timeType;
|
|
if (_type == TType::TICKS)
|
|
_tick = t;
|
|
else
|
|
_frame = t;
|
|
sn = -1;
|
|
_valid = true;
|
|
}
|
|
|
|
Pos::Pos(TempoMap* tl, TimeSigMap* sl, const QString& s)
|
|
{
|
|
tempo = tl;
|
|
sig = sl;
|
|
int m, b, t;
|
|
sscanf(s.toLatin1().data(), "%04d.%02d.%03d", &m, &b, &t);
|
|
_tick = sig->bar2tick(m, b) + t;
|
|
_type = TType::TICKS;
|
|
sn = -1;
|
|
_valid = true;
|
|
}
|
|
|
|
Pos::Pos(TempoMap* tl, TimeSigMap* sl, int measure, int beat, int tick)
|
|
{
|
|
tempo = tl;
|
|
sig = sl;
|
|
_tick = sig->bar2tick(measure, beat) + tick;
|
|
_type = TType::TICKS;
|
|
sn = -1;
|
|
_valid = true;
|
|
}
|
|
|
|
Pos::Pos(TempoMap* tl, TimeSigMap* sl, int min, int sec, int frame, int subframe)
|
|
{
|
|
tempo = tl;
|
|
sig = sl;
|
|
double time = min * 60.0 + sec;
|
|
|
|
double f = frame + subframe/100.0;
|
|
switch (MScore::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 = TType::FRAMES;
|
|
_frame = lrint(time * MScore::sampleRate);
|
|
sn = -1;
|
|
_valid = true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setType
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::setType(TType t)
|
|
{
|
|
if (t == _type)
|
|
return;
|
|
|
|
if (_type == TType::TICKS) {
|
|
// convert from ticks to frames
|
|
_frame = tempo->tick2time(_tick, _frame, &sn) * MScore::sampleRate;
|
|
}
|
|
else {
|
|
// convert from frames to ticks
|
|
_tick = tempo->time2tick(_frame / MScore::sampleRate, _tick, &sn);
|
|
}
|
|
_type = t;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// operator+=
|
|
//---------------------------------------------------------
|
|
|
|
Pos& Pos::operator+=(const Pos& a)
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
_frame += a.frame();
|
|
else
|
|
_tick += a.tick();
|
|
sn = -1; // invalidate cached values
|
|
return *this;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// operator-=
|
|
//---------------------------------------------------------
|
|
|
|
Pos& Pos::operator-=(const Pos& a)
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
_frame -= a.frame();
|
|
else
|
|
_tick -= a.tick();
|
|
sn = -1; // invalidate cached values
|
|
return *this;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// operator+=
|
|
//---------------------------------------------------------
|
|
|
|
Pos& Pos::operator+=(int a)
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
_frame += a;
|
|
else
|
|
_tick += a;
|
|
sn = -1; // invalidate cached values
|
|
return *this;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// operator-=
|
|
//---------------------------------------------------------
|
|
|
|
Pos& Pos::operator-=(int a)
|
|
{
|
|
if (_type == TType::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 == TType::FRAMES)
|
|
return _frame >= s.frame();
|
|
else
|
|
return _tick >= s.tick();
|
|
}
|
|
|
|
bool Pos::operator>(const Pos& s) const
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
return _frame > s.frame();
|
|
else
|
|
return _tick > s.tick();
|
|
}
|
|
|
|
bool Pos::operator<(const Pos& s) const
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
return _frame < s.frame();
|
|
else
|
|
return _tick < s.tick();
|
|
}
|
|
|
|
bool Pos::operator<=(const Pos& s) const
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
return _frame <= s.frame();
|
|
else
|
|
return _tick <= s.tick();
|
|
}
|
|
|
|
bool Pos::operator==(const Pos& s) const
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
return _frame == s.frame();
|
|
else
|
|
return _tick == s.tick();
|
|
}
|
|
|
|
bool Pos::operator!=(const Pos& s) const
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
return _frame != s.frame();
|
|
else
|
|
return _tick != s.tick();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// tick
|
|
//---------------------------------------------------------
|
|
|
|
unsigned Pos::tick() const
|
|
{
|
|
if (_type == TType::FRAMES)
|
|
_tick = tempo->time2tick(_frame / MScore::sampleRate, _tick, &sn);
|
|
return _tick;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// frame
|
|
//---------------------------------------------------------
|
|
|
|
unsigned Pos::frame() const
|
|
{
|
|
if (_type == TType::TICKS) {
|
|
// qreal time = _frame / MScore::sampleRate;
|
|
// _frame = tempo->tick2time(_tick, time, &sn) * MScore::sampleRate;
|
|
_frame = tempo->tick2time(_tick) * MScore::sampleRate;
|
|
}
|
|
return _frame;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setTick
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::setTick(unsigned pos)
|
|
{
|
|
_tick = pos;
|
|
sn = -1;
|
|
if (_type == TType::FRAMES)
|
|
_frame = tempo->tick2time(pos, &sn) * MScore::sampleRate;
|
|
_valid = true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setFrame
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::setFrame(unsigned pos)
|
|
{
|
|
_frame = pos;
|
|
sn = -1;
|
|
if (_type == TType::TICKS)
|
|
_tick = tempo->time2tick(pos/MScore::sampleRate, &sn);
|
|
_valid = true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::write(Xml& xml, const char* name) const
|
|
{
|
|
if (_type == TType::TICKS)
|
|
xml.tagE(QString("%1 tick=\"%2\"").arg(name).arg(_tick));
|
|
else
|
|
xml.tagE(QString("%1 frame=\"%2\"").arg(name).arg(_frame));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// read
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::read(XmlReader& e)
|
|
{
|
|
sn = -1;
|
|
if (e.hasAttribute("tick")) {
|
|
_tick = e.intAttribute("tick");
|
|
_type = TType::TICKS;
|
|
}
|
|
if (e.hasAttribute("frame")) {
|
|
_frame = e.intAttribute("frame");
|
|
_type = TType::FRAMES;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// PosLen
|
|
//---------------------------------------------------------
|
|
|
|
PosLen::PosLen(TempoMap* tl, TimeSigMap* sl)
|
|
: Pos(tl, sl)
|
|
{
|
|
_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);
|
|
qDebug(" Len(");
|
|
switch(type()) {
|
|
case TType::FRAMES:
|
|
qDebug("samples=%d)", _lenFrame);
|
|
break;
|
|
case TType::TICKS:
|
|
qDebug("ticks=%d)", _lenTick);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Pos::dump(int /*n*/) const
|
|
{
|
|
qDebug("Pos(%s, sn=%d, ", type() == TType::FRAMES ? "Frames" : "Ticks", sn);
|
|
switch(type()) {
|
|
case TType::FRAMES:
|
|
qDebug("samples=%d)", _frame);
|
|
break;
|
|
case TType::TICKS:
|
|
qDebug("ticks=%d)", _tick);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void PosLen::write(Xml& xml, const char* name) const
|
|
{
|
|
if (type() == TType::TICKS)
|
|
xml.tagE(QString("%1 tick=\"%2\" len=\"%3\"").arg(name).arg(tick()).arg(_lenTick));
|
|
else
|
|
xml.tagE(QString("%1 sample=\"%2\" len=\"%3\"").arg(name).arg(frame()).arg(_lenFrame));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// read
|
|
//---------------------------------------------------------
|
|
|
|
void PosLen::read(XmlReader& e)
|
|
{
|
|
QString s;
|
|
if (e.hasAttribute("tick")) {
|
|
setType(TType::TICKS);
|
|
setTick(e.intAttribute("tick"));
|
|
}
|
|
if (e.hasAttribute("sample")) {
|
|
setType(TType::FRAMES);
|
|
setFrame(e.intAttribute("sample"));
|
|
}
|
|
if (e.hasAttribute("len")) {
|
|
int n = e.intAttribute("len");
|
|
if (type() == TType::TICKS)
|
|
setLenTick(n);
|
|
else
|
|
setLenFrame(n);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setLenTick
|
|
//---------------------------------------------------------
|
|
|
|
void PosLen::setLenTick(unsigned len)
|
|
{
|
|
_lenTick = len;
|
|
sn = -1;
|
|
if (type() == TType::FRAMES)
|
|
_lenFrame = tempo->tick2time(len, &sn) * MScore::sampleRate;
|
|
else
|
|
_lenTick = len;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setLenFrame
|
|
//---------------------------------------------------------
|
|
|
|
void PosLen::setLenFrame(unsigned len)
|
|
{
|
|
sn = -1;
|
|
if (type() == TType::TICKS)
|
|
_lenTick = tempo->time2tick(len/MScore::sampleRate, &sn);
|
|
else
|
|
_lenFrame = len;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// lenTick
|
|
//---------------------------------------------------------
|
|
|
|
unsigned PosLen::lenTick() const
|
|
{
|
|
if (type() == TType::FRAMES)
|
|
_lenTick = tempo->time2tick(_lenFrame/MScore::sampleRate, _lenTick, &sn);
|
|
return _lenTick;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// lenFrame
|
|
//---------------------------------------------------------
|
|
|
|
unsigned PosLen::lenFrame() const
|
|
{
|
|
if (type() == TType::TICKS)
|
|
_lenFrame = tempo->tick2time(_lenTick, _lenFrame, &sn) * MScore::sampleRate;
|
|
return _lenFrame;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// end
|
|
//---------------------------------------------------------
|
|
|
|
Pos PosLen::end() const
|
|
{
|
|
Pos pos(*this);
|
|
pos.invalidSn();
|
|
switch(type()) {
|
|
case TType::FRAMES:
|
|
pos.setFrame(pos.frame() + _lenFrame);
|
|
break;
|
|
case TType::TICKS:
|
|
pos.setTick(pos.tick() + _lenTick);
|
|
break;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setPos
|
|
//---------------------------------------------------------
|
|
|
|
void PosLen::setPos(const Pos& pos)
|
|
{
|
|
switch(pos.type()) {
|
|
case TType::FRAMES:
|
|
setFrame(pos.frame());
|
|
break;
|
|
case TType::TICKS:
|
|
setTick(pos.tick());
|
|
break;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// operator==
|
|
//---------------------------------------------------------
|
|
|
|
bool PosLen::operator==(const PosLen& pl) const
|
|
{
|
|
if (type() == TType::TICKS)
|
|
return (_lenTick == pl._lenTick && Pos::operator==((const Pos&)pl));
|
|
else
|
|
return (_lenFrame==pl._lenFrame && Pos::operator==((const Pos&)pl));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// mbt
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::mbt(int* bar, int* beat, int* tk) const
|
|
{
|
|
sig->tickValues(tick(), bar, beat, tk);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// msf
|
|
//---------------------------------------------------------
|
|
|
|
void Pos::msf(int* min, int* sec, int* fr, int* subFrame) const
|
|
{
|
|
// for further testing:
|
|
|
|
double time = double(frame()) / double(MScore::sampleRate);
|
|
*min = int(time) / 60;
|
|
*sec = int(time) % 60;
|
|
double rest = time - ((*min) * 60 + (*sec));
|
|
switch(MScore::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 = lrint(rest);
|
|
*subFrame = lrint((rest - (*fr)) * 100.0);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// timesig
|
|
//---------------------------------------------------------
|
|
|
|
SigEvent Pos::timesig() const
|
|
{
|
|
return sig->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(sig->raster(tick(), raster));
|
|
}
|
|
|
|
void Pos::upSnap(int raster)
|
|
{
|
|
setTick(sig->raster2(tick(), raster));
|
|
}
|
|
|
|
void Pos::downSnap(int raster)
|
|
{
|
|
setTick(sig->raster1(tick(), raster));
|
|
}
|
|
|
|
Pos Pos::snaped(int raster) const
|
|
{
|
|
return Pos(tempo, sig, sig->raster(tick(), raster));
|
|
}
|
|
|
|
Pos Pos::upSnaped(int raster) const
|
|
{
|
|
return Pos(tempo, sig, sig->raster2(tick(), raster));
|
|
}
|
|
|
|
Pos Pos::downSnaped(int raster) const
|
|
{
|
|
return Pos(tempo, sig, sig->raster1(tick(), raster));
|
|
}
|
|
|
|
}
|
|
|