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/Quantizer.h

248 lines
8.7 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.
*/
#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