Hey! Sorry for the late reply.
On October 1, 2013 02:43:43 AM Florian Jung wrote:
> Hi all,
>
> i'm just trying to implement the time-lock feature for tracks (in the
> audiostreams branch); i want to have it for both audio and midi tracks,
> because they don't differ for that means.
>
> However, there's a problem with the Pos class:
> both Part and EventBase are derived from Pos. While this is perfectly fine
> for Part, it is a bit of a lie for EventBase: because Pos offers tick/frame
> conversion functions (with caching) which rely on the Pos to be an
> *absolute* position. But EventBases are not absolute, but relative to their
> parental Part!
>
> I can see two ways out of this:
> Either on every process() run, we on-the-fly calculate the Events' absolute
> positions (ev.pos()+part.pos()), and use the .tick() or .frame() function of
> it,
That events are relative to their parts has, so far, never warranted me
wanting to change it. Whenever an event's absolute pos was needed,
one simply added the part and event pos to give an absolute pos.
As I say below I think this is happening already in some, probably quite
a few places during process.
So far so good I think - it's the same technique as usual...
> regarding what we need (in the long run, i'd like to use FRAMES in the
> audio driver for both audio and midi,
There is a conversion from ticks to frames when collecting play events and
placing them in our MPEventLists during process for the driver to read.
I guess you want to make all regular EventLists always in frames, too?
midi.cpp : Audio::collectEvents()
{
...
unsigned tick = ev.tick() + offset;
unsigned frame = MusEGlobal::tempomap.tick2frame(tick) + frameOffset;
...
if(MusEGlobal::extSyncFlag.value())
md->addScheduledEvent(MusECore::MidiPlayEvent(tick, port, channel,
MusECore::ME_NOTEON, pitch, velo));
else
md->addScheduledEvent(MusECore::MidiPlayEvent(frame, port, channel,
MusECore::ME_NOTEON, pitch, velo));
Notice that last section, of which similar lines can be found throughout MusE:
Recently I explained how I made external sync using ticks directly,
not frames. I made the MPEventLists use ticks OR frames depending on
if we syncing externally.
However, recently I realized maybe it was possible for me to work with
frames always, even when externally syncing.
I may try to remove all such if() lines like above and revert to frames:
The solution I am thinking is simply to delay incoming external midi
(and outgoing midi, and playback audio) until a second CLOCK event
is received. From the difference between CLOCK 1 and CLOCK 0 we can
finally compute what the tempo was during that short period.
Currently, I did *not* do that ! In the interest of zero-latency, I needed
to collect all incoming external midi events starting *immediately*
at CLOCK 0. Thus there was no CLOCK 1 yet and I could not measure
time difference to give a tempo.
So currently during external sync MusE operates on ticks not frames.
-> The current 'tick' is incremented by each CLOCK event. <-
Well, it *was* a simple, effective and rock-solid solution.
So by using artificial delay (latency) on all incoming and outgoing midi
events in order to wait for the next CLOCK, maybe I can fix this
long-standing issue. (Using ticks means there's poor resolution when
recording at very slow tempos meaning slower CLOCK events.)
Then we can at least have a tempo value to work with.
Maybe even add further latency to allow the audio to sync up...
> but that's not really relevant now)
> This would however make the Pos' class'es tempomap result caching mechanism
> obsolete. Because we're using frames()/tick() only on temporary Pos objects,
> so we need to do tempomap.tick2frame() quite often *on every process() run!*
> pro/contra:
> + stays compatible with file format
> + hopefully does not involve too much changes
> - very frequent tempomap queries (speed problem??)
I think this is happening already in a few places during process,
so no worries unless massive amounts of events?
> - possible accidental misuse of EventBase::frame()/tick() (they lie!)
How so?
>
> Or we would store the Events with their absolute position. (This is
> possible, because clone parts no longer share the same eventlist, but have
> their own instead.)
> This forces us, however, to move *every single Event* on a Part, when we
> move this Part. Note that AudioStreams or at least WaveEventBase must be
> aware of the event's absolute position anyway (for stretching and seeking,
> both must query the tempomap). Currently this is done by keeping a parental
> part pointer, which is not a problem at all (just a bit unclean).
>
> + very easy interpretation of a Event's position, no need for parental part.
> + tempomap lookups can still be cached (although the cache should be
> recalculated on changes, and not "when necessary", as the latter violates
> realtime constraints)
> - file format anfd copy/paste issues: need to convert from/to relative times
> here.
> - possibly huge amounts of changes during part movement (move every event);
> might violate realtime constraints, but only while editing on purpose.
> And frankly, moving an AudioStream while playing violates realtime
> constraints anyway though buffered by the AudioPrefetch, but this causes
> other issues... Just don't do that.
>
> I find the second solution cleaner, though possibly more work-intensive. But
> i hope the cleanness pays out one day...
>
>
> Please discuss this. Which solution would you prefer? Tim, haven't you
> already thought about time locking some time ago?
So I guess I'm leaning for the first option: Business as usual?
Thanks.
Tim.
------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134791&iu=/4140/ostg.clktrk
_______________________________________________
Lmuse-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lmuse-developer