You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rosegarden/src/base/LegatoQuantizer.cpp

139 lines
3.1 KiB

/*
Rosegarden
A sequencer and musical notation editor.
This program is Copyright 2000-2008
Guillaume Laurent <glaurent@telegraph-road.org>,
Chris Cannam <cannam@all-day-breakfast.com>,
Richard Bown <bownie@bownie.com>
The moral right of the authors to claim authorship of this work
has been asserted.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. See the file
COPYING included with this distribution for more information.
*/
#include "LegatoQuantizer.h"
#include "BaseProperties.h"
#include "NotationTypes.h"
#include "Selection.h"
#include "Composition.h"
#include "Profiler.h"
#include <iostream>
#include <cmath>
#include <cstdio> // for sprintf
#include <ctime>
using std::cout;
using std::cerr;
using std::endl;
namespace Rosegarden
{
using namespace BaseProperties;
LegatoQuantizer::LegatoQuantizer(timeT unit) :
Quantizer(RawEventData),
m_unit(unit)
{
if (m_unit < 0) m_unit = Note(Note::Shortest).getDuration();
}
LegatoQuantizer::LegatoQuantizer(std::string source, std::string target, timeT unit) :
Quantizer(source, target),
m_unit(unit)
{
if (m_unit < 0) m_unit = Note(Note::Shortest).getDuration();
}
LegatoQuantizer::LegatoQuantizer(const LegatoQuantizer &q) :
Quantizer(q.m_target),
m_unit(q.m_unit)
{
// nothing else
}
LegatoQuantizer::~LegatoQuantizer()
{
// nothing
}
void
LegatoQuantizer::quantizeRange(Segment *s,
Segment::iterator from,
Segment::iterator to) const
{
Segment::iterator tmp;
while (from != to) {
quantizeSingle(s, from, tmp);
from = tmp;
if (!s->isBeforeEndMarker(from) ||
(s->isBeforeEndMarker(to) &&
((*from)->getAbsoluteTime() >= (*to)->getAbsoluteTime()))) break;
}
}
void
LegatoQuantizer::quantizeSingle(Segment *s, Segment::iterator i,
Segment::iterator &nexti) const
{
// Stretch each note out to reach the quantized start time of the
// next note whose quantized start time is greater than or equal
// to the end time of this note after quantization
timeT t = getFromSource(*i, AbsoluteTimeValue);
timeT d = getFromSource(*i, DurationValue);
timeT d0(d), t0(t);
timeT barStart = s->getBarStartForTime(t);
t -= barStart;
t = quantizeTime(t);
t += barStart;
nexti = i;
++nexti;
for (Segment::iterator j = i; s->isBeforeEndMarker(j); ++j) {
if (!(*j)->isa(Note::EventType)) continue;
timeT qt = (*j)->getAbsoluteTime();
qt -= barStart;
qt = quantizeTime(qt);
qt += barStart;
if (qt >= t + d) {
d = qt - t;
}
if (qt > t) {
break;
}
}
if (t0 != t || d0 != d) {
setToTarget(s, i, t, d);
nexti = s->findTime(t + d);
}
}
timeT
LegatoQuantizer::quantizeTime(timeT t) const
{
if (m_unit != 0) {
timeT low = (t / m_unit) * m_unit;
timeT high = low + m_unit;
t = ((high - t > t - low) ? low : high);
}
return t;
}
}