summaryrefslogtreecommitdiffstats
path: root/src/commands/segment/CreateTempoMapFromSegmentCommand.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
commit145364a8af6a1fec06556221e66d4b724a62fc9a (patch)
tree53bd71a544008c518034f208d64c932dc2883f50 /src/commands/segment/CreateTempoMapFromSegmentCommand.cpp
downloadrosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz
rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/commands/segment/CreateTempoMapFromSegmentCommand.cpp')
-rw-r--r--src/commands/segment/CreateTempoMapFromSegmentCommand.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/commands/segment/CreateTempoMapFromSegmentCommand.cpp b/src/commands/segment/CreateTempoMapFromSegmentCommand.cpp
new file mode 100644
index 0000000..e548875
--- /dev/null
+++ b/src/commands/segment/CreateTempoMapFromSegmentCommand.cpp
@@ -0,0 +1,166 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio 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 <richard.bown@ferventsoftware.com>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ 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 "CreateTempoMapFromSegmentCommand.h"
+
+#include <klocale.h>
+#include "misc/Debug.h"
+#include "base/Composition.h"
+#include "base/NotationTypes.h"
+#include "base/RealTime.h"
+#include "base/Segment.h"
+
+
+namespace Rosegarden
+{
+
+CreateTempoMapFromSegmentCommand::CreateTempoMapFromSegmentCommand(Segment *groove) :
+ KNamedCommand(i18n("Set Tempos from Beat Segment")),
+ m_composition(groove->getComposition())
+{
+ initialise(groove);
+}
+
+CreateTempoMapFromSegmentCommand::~CreateTempoMapFromSegmentCommand()
+{
+ // nothing
+}
+
+void
+CreateTempoMapFromSegmentCommand::execute()
+{
+ for (TempoMap::iterator i = m_oldTempi.begin(); i != m_oldTempi.end(); ++i) {
+ int n = m_composition->getTempoChangeNumberAt(i->first);
+ if (n < m_composition->getTempoChangeCount()) {
+ m_composition->removeTempoChange(n);
+ }
+ }
+
+ for (TempoMap::iterator i = m_newTempi.begin(); i != m_newTempi.end(); ++i) {
+ m_composition->addTempoAtTime(i->first, i->second);
+ }
+}
+
+void
+CreateTempoMapFromSegmentCommand::unexecute()
+{
+ for (TempoMap::iterator i = m_newTempi.begin(); i != m_newTempi.end(); ++i) {
+ int n = m_composition->getTempoChangeNumberAt(i->first);
+ if (n < m_composition->getTempoChangeCount()) {
+ m_composition->removeTempoChange(n);
+ }
+ }
+
+ for (TempoMap::iterator i = m_oldTempi.begin(); i != m_oldTempi.end(); ++i) {
+ m_composition->addTempoAtTime(i->first, i->second);
+ }
+}
+
+void
+CreateTempoMapFromSegmentCommand::initialise(Segment *s)
+{
+ m_oldTempi.clear();
+ m_newTempi.clear();
+
+ //!!! need an additional option: per-chord, per-beat, per-bar.
+ // Let's work per-beat for the moment. Even for this, we should
+ // probably use TimeSignature.getDivisions()
+
+ std::vector<timeT> beatTimeTs;
+ std::vector<RealTime> beatRealTimes;
+
+ int startBar = m_composition->getBarNumber(s->getStartTime());
+ int barNo = startBar;
+ int beat = 0;
+
+ for (Segment::iterator i = s->begin(); s->isBeforeEndMarker(i); ++i) {
+ if ((*i)->isa(Note::EventType)) {
+
+ bool isNew;
+ TimeSignature sig =
+ m_composition->getTimeSignatureInBar(barNo, isNew);
+
+ beatTimeTs.push_back(m_composition->getBarStart(barNo) +
+ beat * sig.getBeatDuration());
+
+ if (++beat >= sig.getBeatsPerBar()) {
+ ++barNo;
+ beat = 0;
+ }
+
+ beatRealTimes.push_back(s->getComposition()->getElapsedRealTime
+ ((*i)->getAbsoluteTime()));
+ }
+ }
+
+ if (beatTimeTs.size() < 2)
+ return ;
+
+ tempoT prevTempo = 0;
+
+ // set up m_oldTempi and prevTempo
+
+ for (int i = m_composition->getTempoChangeNumberAt(*beatTimeTs.begin() - 1) + 1;
+ i <= m_composition->getTempoChangeNumberAt(*beatTimeTs.end() - 1); ++i) {
+
+ std::pair<timeT, tempoT> tempoChange =
+ m_composition->getTempoChange(i);
+ m_oldTempi[tempoChange.first] = tempoChange.second;
+ if (prevTempo == 0)
+ prevTempo = tempoChange.second;
+ }
+
+ RG_DEBUG << "starting tempo: " << prevTempo << endl;
+
+ timeT quarter = Note(Note::Crotchet).getDuration();
+
+ for (int beat = 1; beat < beatTimeTs.size(); ++beat) {
+
+ timeT beatTime = beatTimeTs[beat] - beatTimeTs[beat - 1];
+ RealTime beatRealTime = beatRealTimes[beat] - beatRealTimes[beat - 1];
+
+ // Calculate tempo to nearest qpm.
+ // This is 60 / {quarter note duration in seconds}
+ // = 60 / ( {beat in seconds} * {quarter in ticks} / { beat in ticks} )
+ // = ( 60 * {beat in ticks} ) / ( {beat in seconds} * {quarter in ticks} )
+ // Precision is deliberately limited to qpm to avoid silly values.
+
+ double beatSec = double(beatRealTime.sec) +
+ double(beatRealTime.usec() / 1000000.0);
+ double qpm = (60.0 * beatTime) / (beatSec * quarter);
+ tempoT tempo = Composition::getTempoForQpm(int(qpm + 0.001));
+
+ RG_DEBUG << "prev beat: " << beatTimeTs[beat] << ", prev beat real time " << beatRealTimes[beat] << endl;
+ RG_DEBUG << "time " << beatTime << ", rt " << beatRealTime << ", beatSec " << beatSec << ", tempo " << tempo << endl;
+
+ if (tempo != prevTempo) {
+ m_newTempi[beatTimeTs[beat - 1]] = tempo;
+ prevTempo = tempo;
+ }
+ }
+
+}
+
+}