summaryrefslogtreecommitdiffstats
path: root/src/base/Quantizer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/Quantizer.h')
-rw-r--r--src/base/Quantizer.h249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/base/Quantizer.h b/src/base/Quantizer.h
new file mode 100644
index 0000000..407b651
--- /dev/null
+++ b/src/base/Quantizer.h
@@ -0,0 +1,249 @@
+// -*- c-basic-offset: 4 -*-
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+#ifndef QUANTIZER_H
+#define QUANTIZER_H
+
+#include "Segment.h"
+#include "Event.h"
+#include "NotationTypes.h"
+#include "FastVector.h"
+#include <string>
+
+namespace Rosegarden {
+
+class EventSelection;
+
+/**
+ The Quantizer class rounds the starting times and durations of note
+ and rest events according to one of a set of possible criteria.
+*/
+
+class Quantizer
+{
+ // define the Quantizer API
+
+public:
+ virtual ~Quantizer();
+
+ /**
+ * Quantize a Segment.
+ */
+ void quantize(Segment *) const;
+
+ /**
+ * Quantize a section of a Segment.
+ */
+ void quantize(Segment *,
+ Segment::iterator from,
+ Segment::iterator to) const;
+
+ /**
+ * Quantize an EventSelection.
+ */
+ void quantize(EventSelection *);
+
+ /**
+ * Quantize a section of a Segment, and force the quantized
+ * results into the formal absolute time and duration of
+ * the events. This is a destructive operation that should
+ * not be carried out except on a user's explicit request.
+ * (If target is RawEventData, this will do nothing besides
+ * quantize. In this case, but no other, unquantize will
+ * still work afterwards.)
+ */
+ void fixQuantizedValues(Segment *,
+ Segment::iterator from,
+ Segment::iterator to) const;
+
+ /**
+ * Return the quantized duration of the event if it has been
+ * quantized -- otherwise just return the unquantized duration.
+ * Do not modify the event.
+ */
+ virtual timeT getQuantizedDuration(const Event *e) const;
+
+ /**
+ * Return the quantized absolute time of the event if it has been
+ * quantized -- otherwise just return the unquantized time. Do
+ * not modify the event.
+ */
+ virtual timeT getQuantizedAbsoluteTime(const Event *e) const;
+
+ /**
+ * Return the unquantized absolute time of the event --
+ * the absolute time that would be restored by a call to
+ * unquantize.
+ */
+ virtual timeT getUnquantizedAbsoluteTime(Event *e) const;
+
+ /**
+ * Return the unquantized absolute time of the event --
+ * the absolute time that would be restored by a call to
+ * unquantize.
+ */
+ virtual timeT getUnquantizedDuration(Event *e) const;
+
+ /**
+ * Unquantize all events in the given range, for this
+ * quantizer. Properties set by other quantizers with
+ * different propertyNamePrefix values will remain.
+ */
+ void unquantize(Segment *,
+ Segment::iterator from, Segment::iterator to) const;
+
+ /**
+ * Unquantize a selection of Events
+ */
+ void unquantize(EventSelection *) const;
+
+ static const std::string RawEventData;
+ static const std::string DefaultTarget;
+ static const std::string GlobalSource;
+ static const std::string NotationPrefix;
+
+protected:
+ /**
+ * \arg source, target : Description of where to find the
+ * times to be quantized, and where to put the quantized results.
+ *
+ * These may be strings, specifying a prefix for the names
+ * of properties to contain the timings, or may be the special
+ * value RawEventData in which case the event's absolute time
+ * and duration will be used instead of properties.
+ *
+ * If source specifies a property prefix for properties that are
+ * found not to exist, they will be pre-filled from the original
+ * timings in the target values before being quantized and then
+ * set back into the target. (This permits a quantizer to write
+ * directly into the Event's absolute time and duration without
+ * losing the original values, because they are backed up
+ * automatically into the source properties.)
+ *
+ * Note that because it's impossible to modify the duration or
+ * absolute time of an event after construction, if target is
+ * RawEventData the quantizer must re-construct each event in
+ * order to adjust its timings. This operation (deliberately)
+ * loses any non-persistent properties in the events. This
+ * does not happen if target is a property prefix.
+ *
+ * Examples:
+ *
+ * -- if source == RawEventData and target == "MyPrefix",
+ * values will be read from the event's absolute time and
+ * duration, quantized, and written into MyPrefixAbsoluteTime
+ * and MyPrefixDuration properties on the event. A call to
+ * unquantize will simply delete these properties.
+ *
+ * -- if source == "MyPrefix" and target == RawEventData,
+ * the MyPrefixAbsoluteTime and MyPrefixDuration will be
+ * populated if necessary from the event's absolute time and
+ * duration, and then quantized and written back into the
+ * event's values. A call to unquantize will write the
+ * MyPrefix-property timings back into the event's values,
+ * and delete the MyPrefix properties.
+ *
+ * -- if source == "YourPrefix" and target == "MyPrefix",
+ * values will be read from YourPrefixAbsoluteTime and
+ * YourPrefixDuration, quantized, and written into the
+ * MyPrefix-properties. This may be useful for piggybacking
+ * onto another quantizer's output.
+ *
+ * -- if source == RawEventData and target == RawEventData,
+ * values will be read from the event's absolute time and
+ * duration, quantized, and written back to these values.
+ */
+ Quantizer(std::string source, std::string target);
+
+ /**
+ * If only target is supplied, source is deduced appropriately
+ * as GlobalSource if target == RawEventData and RawEventData
+ * otherwise.
+ */
+ Quantizer(std::string target);
+
+ /**
+ * To implement a subclass of Quantizer, you should
+ * override either quantizeSingle (if your quantizer is simple
+ * enough only to have to look at a single event at a time) or
+ * quantizeRange. The default implementation of quantizeRange
+ * simply calls quantizeSingle on each non-rest event in turn.
+ * The default implementation of quantizeSingle, as you see,
+ * does nothing.
+ *
+ * Note that implementations of these methods should call
+ * getFromSource and setToTarget to get and set the unquantized
+ * and quantized data; they should not query the event properties
+ * or timings directly.
+ *
+ * NOTE: It is vital that ordering is maintained after
+ * quantization. That is, an event whose absolute time quantizes
+ * to a time t must appear in the original segment before all
+ * events whose times quantize to greater than t. This means you
+ * must quantize the absolute times of non-note events as well as
+ * notes. You don't need to worry about quantizing rests,
+ * however; they're only used for notation and will be
+ * automatically recalculated if the notation quantization values
+ * are seen to change.
+ */
+ virtual void quantizeSingle(Segment *,
+ Segment::iterator) const { }
+
+ /**
+ * See note for quantizeSingle.
+ */
+ virtual void quantizeRange(Segment *,
+ Segment::iterator,
+ Segment::iterator) const;
+
+ std::string m_source;
+ std::string m_target;
+ mutable std::pair<timeT, timeT> m_normalizeRegion;
+
+ enum ValueType { AbsoluteTimeValue = 0, DurationValue = 1 };
+
+ PropertyName m_sourceProperties[2];
+ PropertyName m_targetProperties[2];
+
+public: // should be protected, but gcc-2.95 doesn't like allowing NotationQuantizer::m_impl to access them
+ timeT getFromSource(Event *, ValueType) const;
+ timeT getFromTarget(Event *, ValueType) const;
+ void setToTarget(Segment *, Segment::iterator, timeT t, timeT d) const;
+ mutable FastVector<Event *> m_toInsert;
+
+protected:
+ void removeProperties(Event *) const;
+ void removeTargetProperties(Event *) const;
+ void makePropertyNames();
+
+ void insertNewEvents(Segment *) const;
+
+private: // not provided
+ Quantizer(const Quantizer &);
+ Quantizer &operator=(const Quantizer &);
+ bool operator==(const Quantizer &) const;
+ bool operator!=(const Quantizer & c) const;
+};
+
+
+}
+
+#endif