change default overlapping note strategy to "relax" (i.e. do nothing); fix crash when looping with MIDI data; add back note-off resolution at loop point (if it was actually there) so that notes are turned off (but don't forget Ye Olde Sustain Pedal/Controller) when looping; minor other non-functional tweaks
git-svn-id: svn://localhost/ardour2/branches/3.0@9753 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -1844,9 +1844,7 @@ MidiRegionView::maybe_remove_deleted_note_from_selection (CanvasNoteEvent* cne)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selection.erase (cne) > 0) {
|
||||
cerr << "Erased a CNE from selection\n";
|
||||
}
|
||||
_selection.erase (cne);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "evoral/EventRingBuffer.hpp"
|
||||
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/buffer.h"
|
||||
#include "evoral/EventRingBuffer.hpp"
|
||||
#include "ardour/midi_state_tracker.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
@@ -80,8 +83,19 @@ protected:
|
||||
return (0x80 <= event_type_byte) && (event_type_byte <= 0xE0);
|
||||
}
|
||||
|
||||
inline bool is_note_on(uint8_t event_type_byte) {
|
||||
// mask out channel information
|
||||
return (event_type_byte & 0xF0) == MIDI_CMD_NOTE_ON;
|
||||
}
|
||||
|
||||
inline bool is_note_off(uint8_t event_type_byte) {
|
||||
// mask out channel information
|
||||
return (event_type_byte & 0xF0) == MIDI_CMD_NOTE_OFF;
|
||||
}
|
||||
|
||||
private:
|
||||
volatile uint32_t _channel_mask; // 16 bits mode, 16 bits mask
|
||||
MidiStateTracker _tracker;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -58,6 +58,6 @@ CONFIG_VARIABLE (bool, show_summary, "show-summary", true)
|
||||
CONFIG_VARIABLE (bool, show_group_tabs, "show-group-tabs", true)
|
||||
CONFIG_VARIABLE (bool, external_sync, "external-sync", false)
|
||||
CONFIG_VARIABLE (SyncSource, sync_source, "sync-source", JACK)
|
||||
CONFIG_VARIABLE (InsertMergePolicy, insert_merge_policy, "insert-merge-policy", InsertMergeReject)
|
||||
CONFIG_VARIABLE (InsertMergePolicy, insert_merge_policy, "insert-merge-policy", InsertMergeRelax)
|
||||
CONFIG_VARIABLE (framecnt_t, timecode_offset, "timecode-offset", 0)
|
||||
CONFIG_VARIABLE (bool, timecode_offset_negative, "timecode-offset-negative", true)
|
||||
|
||||
@@ -1413,8 +1413,8 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framepos_t start, framepos_t end)
|
||||
|
||||
#ifndef NDEBUG
|
||||
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
|
||||
"%1 MDS pre-read read from %2 write to %3\n", _name,
|
||||
_playback_buf->get_read_ptr(), _playback_buf->get_write_ptr()));
|
||||
"%1 MDS pre-read read %4..%5 from %2 write to %3\n", _name,
|
||||
_playback_buf->get_read_ptr(), _playback_buf->get_write_ptr(), start, end));
|
||||
// cerr << "================\n";
|
||||
// _playback_buf->dump (cerr);
|
||||
// cerr << "----------------\n";
|
||||
|
||||
@@ -101,17 +101,28 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
|
||||
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 in range %2 .. %3\n", ev_time, start, end));
|
||||
}
|
||||
|
||||
/* lets see if we are going to be able to write this event into dst.
|
||||
*/
|
||||
|
||||
assert(ev_time >= start);
|
||||
|
||||
ev_time -= start;
|
||||
ev_time += offset;
|
||||
|
||||
// write the timestamp to address (write_loc - 1)
|
||||
uint8_t* write_loc = dst.reserve(ev_time, ev_size);
|
||||
if (write_loc == NULL) {
|
||||
// This event marks a loop end (i.e. the next event's timestamp
|
||||
// will be non-monotonic). Don't write it into the buffer - the
|
||||
// significance of this event ends here.
|
||||
|
||||
if (ev_type == LoopEventType) {
|
||||
assert (ev_size == sizeof (framepos_t));
|
||||
framepos_t loop_start;
|
||||
read_contents (ev_size, (uint8_t *) &loop_start);
|
||||
loop_offset = ev_time - loop_start;
|
||||
_tracker.resolve_notes (dst, ev_time);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* lets see if we are going to be able to write this event into dst.
|
||||
*/
|
||||
uint8_t* write_loc = dst.reserve (ev_time, ev_size);
|
||||
if (write_loc == 0) {
|
||||
if (stop_on_overflow_in_dst) {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MidiRingBuffer: overflow in destination MIDI buffer, stopped after %1 events\n", count));
|
||||
break;
|
||||
@@ -124,19 +135,7 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
|
||||
/* we're good to go ahead and read the data now but since we
|
||||
* have the prefix data already, just skip over that
|
||||
*/
|
||||
|
||||
this->increment_read_ptr (prefix_size);
|
||||
|
||||
// This event marks a loop end (i.e. the next event's timestamp will be non-monotonic)
|
||||
if (ev_type == LoopEventType) {
|
||||
assert (ev_size == sizeof (framepos_t));
|
||||
framepos_t loop_start;
|
||||
read_contents (ev_size, (uint8_t *) &loop_start);
|
||||
|
||||
loop_offset = ev_time - loop_start;
|
||||
continue;
|
||||
}
|
||||
|
||||
ev_time += loop_offset;
|
||||
|
||||
uint8_t status;
|
||||
@@ -172,6 +171,13 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
|
||||
#endif
|
||||
|
||||
if (success) {
|
||||
|
||||
if (is_note_on(write_loc[0]) ) {
|
||||
_tracker.add (write_loc[1], write_loc[0] & 0xf);
|
||||
} else if (is_note_off(write_loc[0])) {
|
||||
_tracker.remove (write_loc[1], write_loc[0] & 0xf);
|
||||
}
|
||||
|
||||
if (is_channel_event(status) && get_channel_mode() == ForceChannel) {
|
||||
write_loc[0] = (write_loc[0] & 0xF0) | (get_channel_mask() & 0x0F);
|
||||
}
|
||||
|
||||
@@ -191,6 +191,8 @@ public:
|
||||
inline PatchChanges& patch_changes () { return _patch_changes; }
|
||||
inline const PatchChanges& patch_changes () const { return _patch_changes; }
|
||||
|
||||
void dump (std::ostream&) const;
|
||||
|
||||
private:
|
||||
typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes;
|
||||
public:
|
||||
@@ -332,5 +334,7 @@ private:
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
// template<typename Time> std::ostream& operator<<(std::ostream& o, const Evoral::Sequence<Time>& s) { s.dump (o); return o; }
|
||||
|
||||
#endif // EVORAL_SEQUENCE_HPP
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#ifndef EVORAL_MIDI_UTIL_H
|
||||
#define EVORAL_MIDI_UTIL_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string>
|
||||
@@ -66,9 +68,11 @@ midi_event_size(uint8_t status)
|
||||
return 1;
|
||||
|
||||
case MIDI_CMD_COMMON_SYSEX:
|
||||
std::cerr << "event size called for sysex\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cerr << "event size called for unknown status byte " << std::hex << (int) status << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -687,7 +687,7 @@ Sequence<Time>::add_note_unlocked(const NotePtr note, void* arg)
|
||||
|
||||
_edited = true;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Time>
|
||||
@@ -750,7 +750,7 @@ Sequence<Time>::remove_note_unlocked(const constNotePtr note)
|
||||
}
|
||||
|
||||
if (!erased) {
|
||||
cerr << "Unable to find note to erase" << endl;
|
||||
cerr << "Unable to find note to erase matching " << *note.get() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1214,5 +1214,17 @@ Sequence<Time>::control_list_marked_dirty ()
|
||||
|
||||
template class Sequence<Evoral::MusicalTime>;
|
||||
|
||||
template<typename Time>
|
||||
void
|
||||
Sequence<Time>::dump (ostream& str) const
|
||||
{
|
||||
Sequence<Time>::const_iterator i;
|
||||
str << "+++ dump\n";
|
||||
for (i = begin(); i != end(); ++i) {
|
||||
str << *i << endl;
|
||||
}
|
||||
str << "--- dump\n";
|
||||
}
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
|
||||
Reference in New Issue
Block a user