mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
- Fixes for some recording bugs
- Working MIDI playback - Various SMF fixes - Loading of MIDI containing sessions w/o clobbering .mid files - Varispeed MIDI fixes (still no reverse though) - Fix for crazy rec-region sizes - Throttled MIDI diskstream flush based on time passed (related to rec-region fix) - Fixed playback of MIDI regions not positioned at origin (time stamp translation) - Commented/removed old debug print statements (though some still remain) git-svn-id: svn://localhost/ardour2/branches/midi@844 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
50baf0382f
commit
ea71de2784
9 changed files with 128 additions and 71 deletions
|
|
@ -232,7 +232,7 @@ MidiStreamView::setup_rec_box ()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
|
// cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
|
||||||
|
|
||||||
if (!rec_rects.empty() || !rec_regions.empty()) {
|
if (!rec_rects.empty() || !rec_regions.empty()) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,7 @@ class MidiDiskstream : public Diskstream
|
||||||
RingBufferNPT<CaptureTransition>* _capture_transition_buf;
|
RingBufferNPT<CaptureTransition>* _capture_transition_buf;
|
||||||
//RingBufferNPT<RawMidi>::rw_vector _playback_vector;
|
//RingBufferNPT<RawMidi>::rw_vector _playback_vector;
|
||||||
//RingBufferNPT<RawMidi>::rw_vector _capture_vector;
|
//RingBufferNPT<RawMidi>::rw_vector _capture_vector;
|
||||||
|
jack_nframes_t _last_flush_frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace ARDOUR */
|
}; /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -124,27 +124,7 @@ MidiRingBuffer::clear_event(size_t index)
|
||||||
_ev_buf[index].buffer = 0;
|
_ev_buf[index].buffer = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
inline size_t
|
|
||||||
MidiRingBuffer::read (MidiBuffer& buf)
|
|
||||||
{
|
|
||||||
const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr);
|
|
||||||
|
|
||||||
if (read_space() == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
MidiEvent* const read_ev = &_ev_buf[priv_read_ptr];
|
|
||||||
assert(read_ev->size > 0);
|
|
||||||
buf.push_back(*read_ev);
|
|
||||||
printf("MRB - read %xd %d %d with time %u at index %zu\n",
|
|
||||||
read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time,
|
|
||||||
priv_read_ptr);
|
|
||||||
clear_event(priv_read_ptr);
|
|
||||||
g_atomic_int_set(&_read_ptr, (priv_read_ptr + 1) % _size);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
inline size_t
|
inline size_t
|
||||||
MidiRingBuffer::write (const MidiEvent& ev)
|
MidiRingBuffer::write (const MidiEvent& ev)
|
||||||
{
|
{
|
||||||
|
|
@ -175,7 +155,7 @@ MidiRingBuffer::write (const MidiEvent& ev)
|
||||||
assert(write_ev->size = ev.size);
|
assert(write_ev->size = ev.size);
|
||||||
|
|
||||||
//last_write_time = ev.time;
|
//last_write_time = ev.time;
|
||||||
printf("(W) read space: %zu\n", read_space());
|
//printf("(W) read space: %zu\n", read_space());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -192,8 +172,6 @@ MidiRingBuffer::read(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end)
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t limit = read_space();
|
size_t limit = read_space();
|
||||||
|
|
||||||
assert(time >= start); // FIXME: deal with skipped cycles/lost notes somehow
|
|
||||||
|
|
||||||
while (time <= end && limit > 0) {
|
while (time <= end && limit > 0) {
|
||||||
MidiEvent* const read_ev = &_ev_buf[priv_read_ptr];
|
MidiEvent* const read_ev = &_ev_buf[priv_read_ptr];
|
||||||
if (time >= start) {
|
if (time >= start) {
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ class MidiSource : public Source
|
||||||
MidiSource (string name);
|
MidiSource (string name);
|
||||||
MidiSource (const XMLNode&);
|
MidiSource (const XMLNode&);
|
||||||
virtual ~MidiSource ();
|
virtual ~MidiSource ();
|
||||||
|
|
||||||
virtual jack_nframes_t read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt) const;
|
virtual jack_nframes_t read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const;
|
||||||
virtual jack_nframes_t write (MidiRingBuffer& src, jack_nframes_t cnt);
|
virtual jack_nframes_t write (MidiRingBuffer& src, jack_nframes_t cnt);
|
||||||
|
|
||||||
virtual void mark_for_remove() = 0;
|
virtual void mark_for_remove() = 0;
|
||||||
|
|
@ -70,7 +70,7 @@ class MidiSource : public Source
|
||||||
int set_state (const XMLNode&);
|
int set_state (const XMLNode&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual jack_nframes_t read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt) const = 0;
|
virtual jack_nframes_t read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const = 0;
|
||||||
virtual jack_nframes_t write_unlocked (MidiRingBuffer& dst, jack_nframes_t cnt) = 0;
|
virtual jack_nframes_t write_unlocked (MidiRingBuffer& dst, jack_nframes_t cnt) = 0;
|
||||||
|
|
||||||
mutable Glib::Mutex _lock;
|
mutable Glib::Mutex _lock;
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ class SMFSource : public MidiSource {
|
||||||
|
|
||||||
int update_header (jack_nframes_t when, struct tm&, time_t);
|
int update_header (jack_nframes_t when, struct tm&, time_t);
|
||||||
int flush_header ();
|
int flush_header ();
|
||||||
|
int flush_footer ();
|
||||||
|
|
||||||
int move_to_trash (const string trash_dir_name);
|
int move_to_trash (const string trash_dir_name);
|
||||||
|
|
||||||
|
|
@ -89,7 +90,7 @@ class SMFSource : public MidiSource {
|
||||||
|
|
||||||
int init (string idstr, bool must_exist);
|
int init (string idstr, bool must_exist);
|
||||||
|
|
||||||
jack_nframes_t read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cn) const;
|
jack_nframes_t read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cn, jack_nframes_t stamp_offset) const;
|
||||||
jack_nframes_t write_unlocked (MidiRingBuffer& dst, jack_nframes_t cnt);
|
jack_nframes_t write_unlocked (MidiRingBuffer& dst, jack_nframes_t cnt);
|
||||||
|
|
||||||
bool find (std::string path, bool must_exist, bool& is_new);
|
bool find (std::string path, bool must_exist, bool& is_new);
|
||||||
|
|
@ -113,7 +114,7 @@ class SMFSource : public MidiSource {
|
||||||
FILE* _fd;
|
FILE* _fd;
|
||||||
jack_nframes_t _last_ev_time; // last frame time written, relative to source start
|
jack_nframes_t _last_ev_time; // last frame time written, relative to source start
|
||||||
uint32_t _track_size;
|
uint32_t _track_size;
|
||||||
uint32_t _header_size;
|
uint32_t _header_size; // size of SMF header, including MTrk chunk header
|
||||||
|
|
||||||
static string _search_path;
|
static string _search_path;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
|
||||||
, _source_port(0)
|
, _source_port(0)
|
||||||
, _write_source(0)
|
, _write_source(0)
|
||||||
, _capture_transition_buf(0)
|
, _capture_transition_buf(0)
|
||||||
|
, _last_flush_frame(0)
|
||||||
{
|
{
|
||||||
/* prevent any write sources from being created */
|
/* prevent any write sources from being created */
|
||||||
|
|
||||||
|
|
@ -93,6 +94,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
|
||||||
, _source_port(0)
|
, _source_port(0)
|
||||||
, _write_source(0)
|
, _write_source(0)
|
||||||
, _capture_transition_buf(0)
|
, _capture_transition_buf(0)
|
||||||
|
, _last_flush_frame(0)
|
||||||
{
|
{
|
||||||
in_set_state = true;
|
in_set_state = true;
|
||||||
init (Recordable);
|
init (Recordable);
|
||||||
|
|
@ -180,6 +182,8 @@ MidiDiskstream::non_realtime_input_change ()
|
||||||
else {
|
else {
|
||||||
seek (_session.transport_frame());
|
seek (_session.transport_frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_last_flush_frame = _session.transport_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -679,6 +683,7 @@ MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill)
|
||||||
|
|
||||||
playback_sample = frame;
|
playback_sample = frame;
|
||||||
file_frame = frame;
|
file_frame = frame;
|
||||||
|
_last_flush_frame = frame;
|
||||||
|
|
||||||
if (complete_refill) {
|
if (complete_refill) {
|
||||||
while ((ret = do_refill_with_alloc ()) > 0) ;
|
while ((ret = do_refill_with_alloc ()) > 0) ;
|
||||||
|
|
@ -915,11 +920,15 @@ MidiDiskstream::do_flush (Session::RunContext context, bool force_flush)
|
||||||
|
|
||||||
_write_data_count = 0;
|
_write_data_count = 0;
|
||||||
|
|
||||||
total = _capture_buf->read_space();
|
if (_last_flush_frame > _session.transport_frame()) {
|
||||||
|
_last_flush_frame = _session.transport_frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
total = _session.transport_frame() - _last_flush_frame;
|
||||||
|
|
||||||
|
|
||||||
// FIXME: put this condition back in! (removed for testing)
|
// FIXME: put this condition back in! (removed for testing)
|
||||||
if (total == 0) { // || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
|
if (total == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
|
||||||
//cerr << "MDS - no flush 1\n";
|
//cerr << "MDS - no flush 1\n";
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -946,9 +955,10 @@ MidiDiskstream::do_flush (Session::RunContext context, bool force_flush)
|
||||||
|
|
||||||
if ((!_write_source) || _write_source->write (*_capture_buf, to_write) != to_write) {
|
if ((!_write_source) || _write_source->write (*_capture_buf, to_write) != to_write) {
|
||||||
//cerr << "MDS - no flush 2\n";
|
//cerr << "MDS - no flush 2\n";
|
||||||
error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
|
error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
|
_last_flush_frame = _session.transport_frame();
|
||||||
//cerr << "MDS - flushed\n";
|
//cerr << "MDS - flushed\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1476,9 +1486,14 @@ MidiDiskstream::use_pending_capture_data (XMLNode& node)
|
||||||
void
|
void
|
||||||
MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end)
|
MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end)
|
||||||
{
|
{
|
||||||
assert(end > start);
|
|
||||||
dst.clear();
|
dst.clear();
|
||||||
assert(dst.size() == 0);
|
assert(dst.size() == 0);
|
||||||
|
|
||||||
|
// I think this happens with reverse varispeed? maybe?
|
||||||
|
if (end <= start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
cerr << "MIDI Diskstream pretending to read" << endl;
|
cerr << "MIDI Diskstream pretending to read" << endl;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,9 +225,9 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst,
|
||||||
|
|
||||||
return dur;
|
return dur;
|
||||||
*/
|
*/
|
||||||
jack_nframes_t internal_offset;
|
jack_nframes_t internal_offset = 0;
|
||||||
jack_nframes_t buf_offset;
|
jack_nframes_t src_offset = 0;
|
||||||
jack_nframes_t to_read;
|
jack_nframes_t to_read = 0;
|
||||||
|
|
||||||
/* precondition: caller has verified that we cover the desired section */
|
/* precondition: caller has verified that we cover the desired section */
|
||||||
|
|
||||||
|
|
@ -235,11 +235,11 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst,
|
||||||
|
|
||||||
if (position < _position) {
|
if (position < _position) {
|
||||||
internal_offset = 0;
|
internal_offset = 0;
|
||||||
//buf_offset = _position - position;
|
src_offset = _position - position;
|
||||||
//cnt -= buf_offset;
|
dur -= src_offset;
|
||||||
} else {
|
} else {
|
||||||
internal_offset = position - _position;
|
internal_offset = position - _position;
|
||||||
buf_offset = 0;
|
src_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internal_offset >= _length) {
|
if (internal_offset >= _length) {
|
||||||
|
|
@ -261,11 +261,11 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst,
|
||||||
_read_data_count = 0;
|
_read_data_count = 0;
|
||||||
|
|
||||||
MidiSource& src = midi_source(chan_n);
|
MidiSource& src = midi_source(chan_n);
|
||||||
if (src.read (dst, _start + internal_offset, to_read) != to_read) {
|
if (src.read (dst, _start + internal_offset, to_read, _position) != to_read) {
|
||||||
return 0; /* "read nothing" */
|
return 0; /* "read nothing" */
|
||||||
}
|
}
|
||||||
|
|
||||||
_read_data_count += src.read_data_count();
|
_read_data_count += src.read_data_count(); // FIXME: semantics?
|
||||||
|
|
||||||
return to_read;
|
return to_read;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,10 +91,10 @@ MidiSource::set_state (const XMLNode& node)
|
||||||
}
|
}
|
||||||
|
|
||||||
jack_nframes_t
|
jack_nframes_t
|
||||||
MidiSource::read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt) const
|
MidiSource::read (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const
|
||||||
{
|
{
|
||||||
Glib::Mutex::Lock lm (_lock);
|
Glib::Mutex::Lock lm (_lock);
|
||||||
return read_unlocked (dst, start, cnt);
|
return read_unlocked (dst, start, cnt, stamp_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
jack_nframes_t
|
jack_nframes_t
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,8 @@ SMFSource::SMFSource (std::string path, Flag flags)
|
||||||
, _timeline_position (0)
|
, _timeline_position (0)
|
||||||
, _fd (0)
|
, _fd (0)
|
||||||
, _last_ev_time(0)
|
, _last_ev_time(0)
|
||||||
, _track_size(4) // compensate for the EOT event
|
, _track_size(4) // 4 bytes for the ever-present EOT event
|
||||||
|
, _header_size(22)
|
||||||
{
|
{
|
||||||
/* constructor used for new internal-to-session files. file cannot exist */
|
/* constructor used for new internal-to-session files. file cannot exist */
|
||||||
|
|
||||||
|
|
@ -81,7 +82,8 @@ SMFSource::SMFSource (const XMLNode& node)
|
||||||
, _timeline_position (0)
|
, _timeline_position (0)
|
||||||
, _fd (0)
|
, _fd (0)
|
||||||
, _last_ev_time(0)
|
, _last_ev_time(0)
|
||||||
, _track_size(4) // compensate for the EOT event
|
, _track_size(4) // 4 bytes for the ever-present EOT event
|
||||||
|
, _header_size(22)
|
||||||
{
|
{
|
||||||
/* constructor used for existing internal-to-session files. file must exist */
|
/* constructor used for existing internal-to-session files. file must exist */
|
||||||
|
|
||||||
|
|
@ -139,16 +141,29 @@ SMFSource::open()
|
||||||
{
|
{
|
||||||
cerr << "Opening SMF file " << path() << " writeable: " << writable() << endl;
|
cerr << "Opening SMF file " << path() << " writeable: " << writable() << endl;
|
||||||
|
|
||||||
// FIXME
|
assert(writable()); // FIXME;
|
||||||
//_fd = fopen(path().c_str(), writable() ? "r+" : "r");
|
|
||||||
_fd = fopen(path().c_str(), "w+");
|
|
||||||
|
|
||||||
// FIXME: pad things out so writing the header later doesn't overwrite data
|
_fd = fopen(path().c_str(), "r+");
|
||||||
flush_header();
|
|
||||||
|
|
||||||
// FIXME
|
// File already exists
|
||||||
//return (_fd == 0) ? -1 : 0;
|
if (_fd) {
|
||||||
return 0;
|
fseek(_fd, _header_size - 4, 0);
|
||||||
|
uint32_t track_size_be = 0;
|
||||||
|
fread(&track_size_be, 4, 1, _fd);
|
||||||
|
_track_size = GUINT32_FROM_BE(track_size_be);
|
||||||
|
cerr << "SMF - read track size " << _track_size;
|
||||||
|
|
||||||
|
// We're making a new file
|
||||||
|
} else {
|
||||||
|
_fd = fopen(path().c_str(), "w+");
|
||||||
|
_track_size = 0;
|
||||||
|
|
||||||
|
// write a tentative header just to pad things out so writing happens in the right spot
|
||||||
|
flush_header();
|
||||||
|
// FIXME: write the footer here too so it's a valid SMF (screw up writing ATM though)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (_fd == 0) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -184,13 +199,24 @@ SMFSource::flush_header ()
|
||||||
write_chunk_header("MTrk", _track_size);
|
write_chunk_header("MTrk", _track_size);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
_header_size = 22;
|
|
||||||
|
|
||||||
fflush(_fd);
|
fflush(_fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SMFSource::flush_footer()
|
||||||
|
{
|
||||||
|
cerr << "SMF - Writing EOT\n";
|
||||||
|
|
||||||
|
fseek(_fd, 0, SEEK_END);
|
||||||
|
write_var_len(1); // whatever...
|
||||||
|
char eot[4] = { 0xFF, 0x2F, 0x00 }; // end-of-track meta-event
|
||||||
|
fwrite(eot, 1, 4, _fd);
|
||||||
|
fflush(_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the offset of the first event in the file with a time past @a start,
|
/** Returns the offset of the first event in the file with a time past @a start,
|
||||||
* relative to the start of the source.
|
* relative to the start of the source.
|
||||||
*
|
*
|
||||||
|
|
@ -218,13 +244,18 @@ SMFSource::find_first_event_after(jack_nframes_t start)
|
||||||
/** Read an event from the current position in file.
|
/** Read an event from the current position in file.
|
||||||
*
|
*
|
||||||
* File position MUST be at the beginning of a delta time, or this will die very messily.
|
* File position MUST be at the beginning of a delta time, or this will die very messily.
|
||||||
* ev.buffer must be of size ev.size, and large enough for the event.
|
* ev.buffer must be of size ev.size, and large enough for the event. The returned event
|
||||||
|
* will have it's time field set to it's delta time (so it's the caller's responsibility
|
||||||
|
* to calculate a real time for the event).
|
||||||
*
|
*
|
||||||
* Returns 0 on success, -1 if EOF.
|
* Returns event length (including status byte) on success, 0 if event was
|
||||||
|
* skipped (eg a meta event), or -1 on EOF (or end of track).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
SMFSource::read_event(MidiEvent& ev) const
|
SMFSource::read_event(MidiEvent& ev) const
|
||||||
{
|
{
|
||||||
|
// - 4 is for the EOT event, which we don't actually want to read
|
||||||
|
//if (feof(_fd) || ftell(_fd) >= _header_size + _track_size - 4) {
|
||||||
if (feof(_fd)) {
|
if (feof(_fd)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -232,10 +263,24 @@ SMFSource::read_event(MidiEvent& ev) const
|
||||||
uint32_t delta_time = read_var_len();
|
uint32_t delta_time = read_var_len();
|
||||||
int status = fgetc(_fd);
|
int status = fgetc(_fd);
|
||||||
assert(status != EOF); // FIXME die gracefully
|
assert(status != EOF); // FIXME die gracefully
|
||||||
|
if (status == 0xFF) {
|
||||||
|
assert(!feof(_fd));
|
||||||
|
int type = fgetc(_fd);
|
||||||
|
if ((unsigned char)type == 0x2F) {
|
||||||
|
cerr << "SMF - hit EOT" << endl;
|
||||||
|
return -1; // we hit the logical EOF anyway...
|
||||||
|
} else {
|
||||||
|
ev.size = 0;
|
||||||
|
ev.time = delta_time; // this is needed regardless
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ev.buffer[0] = (unsigned char)status;
|
ev.buffer[0] = (unsigned char)status;
|
||||||
ev.size = midi_event_size(ev.buffer[0]) + 1;
|
ev.size = midi_event_size(ev.buffer[0]) + 1;
|
||||||
fread(ev.buffer+1, 1, ev.size - 1, _fd);
|
fread(ev.buffer+1, 1, ev.size - 1, _fd);
|
||||||
|
ev.time = delta_time;
|
||||||
|
|
||||||
printf("SMF - read event, delta = %u, size = %zu, data = ",
|
printf("SMF - read event, delta = %u, size = %zu, data = ",
|
||||||
delta_time, ev.size);
|
delta_time, ev.size);
|
||||||
for (size_t i=0; i < ev.size; ++i) {
|
for (size_t i=0; i < ev.size; ++i) {
|
||||||
|
|
@ -243,14 +288,16 @@ SMFSource::read_event(MidiEvent& ev) const
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
return 0;
|
return ev.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
jack_nframes_t
|
jack_nframes_t
|
||||||
SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt) const
|
SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const
|
||||||
{
|
{
|
||||||
cerr << "SMF - read " << start << " -- " << cnt;
|
cerr << "SMF - read " << start << " -- " << cnt;
|
||||||
|
|
||||||
|
jack_nframes_t time = 0;
|
||||||
|
|
||||||
// FIXME: ugh
|
// FIXME: ugh
|
||||||
unsigned char ev_buf[MidiBuffer::max_event_size()];
|
unsigned char ev_buf[MidiBuffer::max_event_size()];
|
||||||
MidiEvent ev;
|
MidiEvent ev;
|
||||||
|
|
@ -258,16 +305,31 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframe
|
||||||
ev.size = MidiBuffer::max_event_size();
|
ev.size = MidiBuffer::max_event_size();
|
||||||
ev.buffer = ev_buf;
|
ev.buffer = ev_buf;
|
||||||
|
|
||||||
while (true) {
|
// FIXME: it would be an impressive feat to actually make this any slower :)
|
||||||
|
|
||||||
|
fseek(_fd, _header_size, 0);
|
||||||
|
|
||||||
|
while (!feof(_fd)) {
|
||||||
int ret = read_event(ev);
|
int ret = read_event(ev);
|
||||||
if (ret == -1) {
|
if (ret == -1) { // EOF
|
||||||
|
cerr << "SMF - EOF\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret == 0) { // meta-event (skipped)
|
||||||
|
cerr << "SMF - META\n";
|
||||||
|
time += ev.time; // just accumulate delta time and ignore event
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
time += ev.time; // accumulate delta time
|
||||||
|
ev.time = time; // set ev.time to actual time (relative to source start)
|
||||||
|
|
||||||
if (ev.time >= start) {
|
if (ev.time >= start) {
|
||||||
if (ev.time > start + cnt) {
|
if (ev.time > start + cnt) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
ev.time += stamp_offset;
|
||||||
dst.write(ev);
|
dst.write(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -337,7 +399,10 @@ SMFSource::write_unlocked (MidiRingBuffer& src, jack_nframes_t cnt)
|
||||||
|
|
||||||
fflush(_fd);
|
fflush(_fd);
|
||||||
|
|
||||||
ViewDataRangeReady (_length, cnt); /* EMIT SIGNAL */
|
if (buf.size() > 0) {
|
||||||
|
ViewDataRangeReady (_length, cnt); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
|
||||||
update_length(_length, cnt);
|
update_length(_length, cnt);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
@ -394,13 +459,7 @@ SMFSource::mark_streaming_write_completed ()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "SMF - Writing EOT\n";
|
flush_footer();
|
||||||
|
|
||||||
fseek(_fd, 0, SEEK_END);
|
|
||||||
write_var_len(1); // whatever...
|
|
||||||
char eot[4] = { 0xFF, 0x2F, 0x00 }; // end-of-track meta-event
|
|
||||||
fwrite(eot, 1, 4, _fd);
|
|
||||||
fflush(_fd);
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
Glib::Mutex::Lock lm (_lock);
|
Glib::Mutex::Lock lm (_lock);
|
||||||
|
|
@ -685,7 +744,7 @@ SMFSource::write_var_len(uint32_t value)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printf("Writing var len byte %X\n", (unsigned char)buffer);
|
//printf("Writing var len byte %X\n", (unsigned char)buffer);
|
||||||
++ret;
|
++ret;
|
||||||
fputc(buffer, _fd);
|
fputc(buffer, _fd);
|
||||||
if (buffer & 0x80)
|
if (buffer & 0x80)
|
||||||
|
|
@ -702,6 +761,9 @@ SMFSource::read_var_len() const
|
||||||
{
|
{
|
||||||
assert(!feof(_fd));
|
assert(!feof(_fd));
|
||||||
|
|
||||||
|
//int offset = ftell(_fd);
|
||||||
|
//cerr << "SMF - reading var len at " << offset << endl;
|
||||||
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue