Session::process() returns early with Session::_silent set to true. AudioBuffer::set_data()
was never set for (at least) the LTC output port. PortManager::cycle_end() calls
AudioBuffer::silence() which used to assume that get_buffer() must have been called. But it
was not, because that should have happened in Session::process().
So check AudioBuffer::data() and call get_buffer() if required.
The trim processor was moved to the front after the internal return was,
so the trim setting was applied before the signal coming from other
tracks/busses sends was mixed in. Change the order so that trim applies
to audio from internal sends as well.
To export a MIDI region to a file, the code used MidiRegion::clone()
since it takes care of creating a new file-backed source with the wanted
contents. Nevertheless, it had several side-effects:
- it created and registered a new region which is confusing to users
- it only exported notes that were in the region range, but didn't
remove the region start offset from MIDI events, essentially producing
a spurious silence at the beginning of the exported file (this is not
a problem for region cloning because the newly created region is made
aware of the offset and caters for it).
Add a dedicated code path for export, that uses the new offsetting
capabilities of MidiModel::write_section_to().
MidiModel::write_section_to() only wrote events to the given source if
those events had a time in the given range. Make it able to optionally
offset event times so that the start of the written range corresponds to
time 0 in the source.
This allows a TmpFile pointer to be either a Sync or Async (Threaded)
writer. As result we must be able to handle both RT and non RT processing.
Still, post-processing (normalization and encoding) should always
happen faster than realtime (freewheeling).
Since jack does not allow a client to change to freewheeling from within
the process-callback, the async-writer disk-thread FileFlushed is used
to initiate post-processing.
When flushing the buffers of Delivery processors owned by a Route/Track,
inner deliveries of PortInsert processors were missed since PortInsert
is not a Delivery subclass, but rather owns a Delivery as a private
member. Expose a flush_buffers() for PortInsert and call it too.
This is correct since (external) Send is a Delivery subclass, so that
just makes the send part of inserts behave as external sends do.
Route::no_roll(), Route::roll(), Track::no_roll(), AudioTrack::roll()
and MidiTrack::roll() all had the exact same loop for flushing buffers
of their Delivery processors. That was a lot of replicated code that had
to be kept synchronised by hand. Put that code into a protected method
Route::flush_processor_buffers_locked() which is called instead.