Differentiate between pitch-shift (for audio) and transpose (for MIDI). Fixes #3940.

git-svn-id: svn://localhost/ardour2/branches/3.0@9299 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington
2011-04-06 02:04:37 +00:00
parent ebb31e504b
commit e8c8befb87
13 changed files with 202 additions and 6 deletions

View File

@@ -261,6 +261,7 @@ public:
boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
void insert_silence_at_start (TimeType);
void transpose (TimeType, TimeType, int);
protected:
int resolve_overlaps_unlocked (const NotePtr, void* arg = 0);

View File

@@ -109,6 +109,7 @@ class MidiRegion : public Region
boost::shared_ptr<const MidiModel> model() const { return midi_source()->model(); }
void fix_negative_start ();
void transpose (int);
protected:

View File

@@ -1899,3 +1899,43 @@ MidiModel::insert_silence_at_start (TimeType t)
apply_command_as_subcommand (s->session(), c);
}
}
/** Transpose notes in a time range by a given number of semitones. Notes
* will be clamped at 0 and 127 if the transposition would make them exceed
* that range.
*
* @param from Start time.
* @param end End time.
* @param semitones Number of semitones to transpose by (+ve is higher, -ve is lower).
*/
void
MidiModel::transpose (TimeType from, TimeType to, int semitones)
{
boost::shared_ptr<const MidiSource> s = midi_source ();
NoteDiffCommand* c = new_note_diff_command (_("transpose"));
for (Notes::iterator i = notes().begin(); i != notes().end(); ++i) {
if ((*i)->time() >= to) {
/* finished */
break;
} else if ((*i)->time() >= from) {
int new_note = (*i)->note() + semitones;
if (new_note < 0) {
new_note = 0;
} else if (new_note > 127) {
new_note = 127;
}
c->change (*i, NoteDiffCommand::NoteNumber, (uint8_t) new_note);
}
}
apply_command (s->session (), c);
}

View File

@@ -378,3 +378,11 @@ MidiRegion::fix_negative_start ()
model()->insert_silence_at_start (c.from (-_start));
_start = 0;
}
/** Transpose the notes in this region by a given number of semitones */
void
MidiRegion::transpose (int semitones)
{
BeatsFramesConverter c (_session.tempo_map(), _start);
model()->transpose (c.from (_start), c.from (_start + _length), semitones);
}