diff options
author | David Robillard <d@drobilla.net> | 2006-08-23 04:30:57 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2006-08-23 04:30:57 +0000 |
commit | ea71de278461b2bc0240515b82bb56ef68f5eee3 (patch) | |
tree | cbc615b5f4aa0d01f2d479abc214f6798fd67862 /libs/ardour | |
parent | 50baf0382f1f98793dff151bd0a940a4d140d6c0 (diff) |
- 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
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_ring_buffer.h | 24 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_source.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/smf_source.h | 5 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 23 | ||||
-rw-r--r-- | libs/ardour/midi_region.cc | 16 | ||||
-rw-r--r-- | libs/ardour/midi_source.cc | 4 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 118 |
8 files changed, 127 insertions, 70 deletions
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index ccff993638..0e4aed1929 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -159,6 +159,7 @@ class MidiDiskstream : public Diskstream RingBufferNPT<CaptureTransition>* _capture_transition_buf; //RingBufferNPT<RawMidi>::rw_vector _playback_vector; //RingBufferNPT<RawMidi>::rw_vector _capture_vector; + jack_nframes_t _last_flush_frame; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h index 08ddfd6ca3..662f5a8350 100644 --- a/libs/ardour/ardour/midi_ring_buffer.h +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -124,27 +124,7 @@ MidiRingBuffer::clear_event(size_t index) _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 MidiRingBuffer::write (const MidiEvent& ev) { @@ -175,7 +155,7 @@ MidiRingBuffer::write (const MidiEvent& ev) assert(write_ev->size = ev.size); //last_write_time = ev.time; - printf("(W) read space: %zu\n", read_space()); + //printf("(W) read space: %zu\n", read_space()); return 1; } @@ -192,8 +172,6 @@ MidiRingBuffer::read(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end) size_t count = 0; size_t limit = read_space(); - assert(time >= start); // FIXME: deal with skipped cycles/lost notes somehow - while (time <= end && limit > 0) { MidiEvent* const read_ev = &_ev_buf[priv_read_ptr]; if (time >= start) { diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index f1ede9c842..757e33f70e 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -46,8 +46,8 @@ class MidiSource : public Source MidiSource (string name); MidiSource (const XMLNode&); 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 void mark_for_remove() = 0; @@ -70,7 +70,7 @@ class MidiSource : public Source int set_state (const XMLNode&); 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; mutable Glib::Mutex _lock; diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index 31e9c2205d..5c3fdcfec9 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -70,6 +70,7 @@ class SMFSource : public MidiSource { int update_header (jack_nframes_t when, struct tm&, time_t); int flush_header (); + int flush_footer (); int move_to_trash (const string trash_dir_name); @@ -89,7 +90,7 @@ class SMFSource : public MidiSource { 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); bool find (std::string path, bool must_exist, bool& is_new); @@ -113,7 +114,7 @@ class SMFSource : public MidiSource { FILE* _fd; jack_nframes_t _last_ev_time; // last frame time written, relative to source start uint32_t _track_size; - uint32_t _header_size; + uint32_t _header_size; // size of SMF header, including MTrk chunk header static string _search_path; }; diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index b399089a27..40b0b11564 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -68,6 +68,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F , _source_port(0) , _write_source(0) , _capture_transition_buf(0) + , _last_flush_frame(0) { /* prevent any write sources from being created */ @@ -93,6 +94,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node) , _source_port(0) , _write_source(0) , _capture_transition_buf(0) + , _last_flush_frame(0) { in_set_state = true; init (Recordable); @@ -180,6 +182,8 @@ MidiDiskstream::non_realtime_input_change () else { seek (_session.transport_frame()); } + + _last_flush_frame = _session.transport_frame(); } void @@ -679,6 +683,7 @@ MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill) playback_sample = frame; file_frame = frame; + _last_flush_frame = frame; if (complete_refill) { while ((ret = do_refill_with_alloc ()) > 0) ; @@ -915,11 +920,15 @@ MidiDiskstream::do_flush (Session::RunContext context, bool force_flush) _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) - 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"; 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) { //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; } else { + _last_flush_frame = _session.transport_frame(); //cerr << "MDS - flushed\n"; } @@ -1476,9 +1486,14 @@ MidiDiskstream::use_pending_capture_data (XMLNode& node) void MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end) { - assert(end > start); dst.clear(); assert(dst.size() == 0); + + // I think this happens with reverse varispeed? maybe? + if (end <= start) { + return; + } + /* cerr << "MIDI Diskstream pretending to read" << endl; diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index 07cbd279ff..136b2bfc38 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -225,9 +225,9 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, return dur; */ - jack_nframes_t internal_offset; - jack_nframes_t buf_offset; - jack_nframes_t to_read; + jack_nframes_t internal_offset = 0; + jack_nframes_t src_offset = 0; + jack_nframes_t to_read = 0; /* 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) { internal_offset = 0; - //buf_offset = _position - position; - //cnt -= buf_offset; + src_offset = _position - position; + dur -= src_offset; } else { internal_offset = position - _position; - buf_offset = 0; + src_offset = 0; } if (internal_offset >= _length) { @@ -261,11 +261,11 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, _read_data_count = 0; 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" */ } - _read_data_count += src.read_data_count(); + _read_data_count += src.read_data_count(); // FIXME: semantics? return to_read; } diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 1438b1fdbe..c4cfe3c71d 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -91,10 +91,10 @@ MidiSource::set_state (const XMLNode& node) } 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); - return read_unlocked (dst, start, cnt); + return read_unlocked (dst, start, cnt, stamp_offset); } jack_nframes_t diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index a4036a317b..bd5649bc2e 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -56,7 +56,8 @@ SMFSource::SMFSource (std::string path, Flag flags) , _timeline_position (0) , _fd (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 */ @@ -81,7 +82,8 @@ SMFSource::SMFSource (const XMLNode& node) , _timeline_position (0) , _fd (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 */ @@ -139,16 +141,29 @@ SMFSource::open() { cerr << "Opening SMF file " << path() << " writeable: " << writable() << endl; - // FIXME - //_fd = fopen(path().c_str(), writable() ? "r+" : "r"); - _fd = fopen(path().c_str(), "w+"); + assert(writable()); // FIXME; - // FIXME: pad things out so writing the header later doesn't overwrite data - flush_header(); + _fd = fopen(path().c_str(), "r+"); - // FIXME - //return (_fd == 0) ? -1 : 0; - return 0; + // File already exists + if (_fd) { + 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 @@ -184,13 +199,24 @@ SMFSource::flush_header () write_chunk_header("MTrk", _track_size); //} - _header_size = 22; - fflush(_fd); 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, * 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. * * 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 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)) { return -1; } @@ -232,10 +263,24 @@ SMFSource::read_event(MidiEvent& ev) const uint32_t delta_time = read_var_len(); int status = fgetc(_fd); 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.size = midi_event_size(ev.buffer[0]) + 1; fread(ev.buffer+1, 1, ev.size - 1, _fd); - + ev.time = delta_time; + printf("SMF - read event, delta = %u, size = %zu, data = ", delta_time, ev.size); for (size_t i=0; i < ev.size; ++i) { @@ -243,14 +288,16 @@ SMFSource::read_event(MidiEvent& ev) const } printf("\n"); - return 0; + return ev.size; } 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; + jack_nframes_t time = 0; + // FIXME: ugh unsigned char ev_buf[MidiBuffer::max_event_size()]; MidiEvent ev; @@ -258,16 +305,31 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframe ev.size = MidiBuffer::max_event_size(); 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); - if (ret == -1) { + if (ret == -1) { // EOF + cerr << "SMF - EOF\n"; 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 + cnt) { break; } else { + ev.time += stamp_offset; dst.write(ev); } } @@ -337,7 +399,10 @@ SMFSource::write_unlocked (MidiRingBuffer& src, jack_nframes_t cnt) fflush(_fd); - ViewDataRangeReady (_length, cnt); /* EMIT SIGNAL */ + if (buf.size() > 0) { + ViewDataRangeReady (_length, cnt); /* EMIT SIGNAL */ + } + update_length(_length, cnt); return cnt; } @@ -394,13 +459,7 @@ SMFSource::mark_streaming_write_completed () return; } - 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); + flush_footer(); #if 0 Glib::Mutex::Lock lm (_lock); @@ -685,7 +744,7 @@ SMFSource::write_var_len(uint32_t value) } while (true) { - printf("Writing var len byte %X\n", (unsigned char)buffer); + //printf("Writing var len byte %X\n", (unsigned char)buffer); ++ret; fputc(buffer, _fd); if (buffer & 0x80) @@ -702,6 +761,9 @@ SMFSource::read_var_len() const { assert(!feof(_fd)); + //int offset = ftell(_fd); + //cerr << "SMF - reading var len at " << offset << endl; + uint32_t value; unsigned char c; |