Handling events that cross structural time points

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Handling events that cross structural time points

jamshark70-2
Sorry in advance for what is to follow.

I just literally threw my computer a couple of feet because I was working
on the problem of sustaining musical events through a structural time
point. I deliberately aimed so that it would land flat on a pillow, but...
you get the point. A conceptual weakness in SuperCollider has now reached
what is, for me, such a critical point that I couldn't get through a
programming session without literally hurling my computer through the air.

So. I'm organizing materials into phrases. The event stream *must* wake up
at a phrase boundary to decide which phrase to play next. Because
SuperCollider streams have no future, the content of the next phrase cannot
be decided until the phrase boundary.

So... what if a note starts near the end of the previous phrase, and needs
to tie across the barline until the first sounding note of the next phrase?

SC events work wonderfully if you know in advance how long the note should
sustain. But if you don't know *right now* if the next note will occur on
beat 2 or 3.25 of the next bar, things become inordinately complex very
quickly.

I have been working on this problem for literally two months, and I had
almost cracked it tonight, when I ran into an unrelated problem with the
technique I was using to debug the last problem, and... Really. No.
Seriously. WHY IS THIS SO HARD?

It's not a far-fetched musical requirement, but it's making me feel like a
novice programmer.

I apologize somewhat -- I realize this is 90% venting and there might not
be any possible structural changes in SC that could make this less painful.
But I'm really deeply discouraged. 2.5 years working on a live coding
system and this one problem puts the whole project in jeopardy. It's really
impossible to manage pitched material without ties over the barline. And
I'm not prepared to accept that SC can't handle this.

Beg pardon for asking for advice about my direction here, but I have nobody
to talk to locally and I'm feeling lost. I'm not making music anymore, just
struggling with these damn problems. I'm either almost through them, or
I've been going down the wrong path for two years and I had better just
throw away everything I've done in that time. It's not easy to ponder.

Thanks for listening.
hjh

Sent with AquaMail for Android
http://www.aqua-mail.com




_______________________________________________
sc-dev mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/
Reply | Threaded
Open this post in threaded view
|

Re: Handling events that cross structural time points

Kuivila, Ronald
Hi James,

Here are a few random thoughts in response...

PatternConductor was a first stab at thinking about this kind of issue.
It is not right for the needs you describe but it might open a door.  The basic idea there
is to have the clock's  future action/event queue be a part of the eventstreamplayer itself.
This allows realtime "conduction" to be  implemented by altering the tempo of the PatternConductor's
private clock.

But, as you suggest, what we really need is a consistent model for additional layers of future action queues built
into the specification of the eventstream rather than the player.   I am having a hard time thinking this through.
On the one hand it might be added to the cleanup framework - so an event is left hanging waiting for change of
state from its parent eventstream.  But that sounds like a nightmare to implement....

Actually, Ppar's fiddling of delta might be a symptom of the basic structural issue.
Once you pass through Ppar there is no  possibility of changing the order of execution
of parallel event streams. So, contingent actions need to be held by the eventstream itself
before it is subject to Ppar's fiddling.  Or Ppar would do that for each of its clients.

Cheers,

RJK

> On Mar 9, 2017, at 10:16 AM, James Harkins <[hidden email]> wrote:
>
> Sorry in advance for what is to follow.
>
> I just literally threw my computer a couple of feet because I was working on the problem of sustaining musical events through a structural time point. I deliberately aimed so that it would land flat on a pillow, but... you get the point. A conceptual weakness in SuperCollider has now reached what is, for me, such a critical point that I couldn't get through a programming session without literally hurling my computer through the air.
>
> So. I'm organizing materials into phrases. The event stream *must* wake up at a phrase boundary to decide which phrase to play next. Because SuperCollider streams have no future, the content of the next phrase cannot be decided until the phrase boundary.
>
> So... what if a note starts near the end of the previous phrase, and needs to tie across the barline until the first sounding note of the next phrase?
>
> SC events work wonderfully if you know in advance how long the note should sustain. But if you don't know *right now* if the next note will occur on beat 2 or 3.25 of the next bar, things become inordinately complex very quickly.
>
> I have been working on this problem for literally two months, and I had almost cracked it tonight, when I ran into an unrelated problem with the technique I was using to debug the last problem, and... Really. No. Seriously. WHY IS THIS SO HARD?
>
> It's not a far-fetched musical requirement, but it's making me feel like a novice programmer.
>
> I apologize somewhat -- I realize this is 90% venting and there might not be any possible structural changes in SC that could make this less painful. But I'm really deeply discouraged. 2.5 years working on a live coding system and this one problem puts the whole project in jeopardy. It's really impossible to manage pitched material without ties over the barline. And I'm not prepared to accept that SC can't handle this.
>
> Beg pardon for asking for advice about my direction here, but I have nobody to talk to locally and I'm feeling lost. I'm not making music anymore, just struggling with these damn problems. I'm either almost through them, or I've been going down the wrong path for two years and I had better just throw away everything I've done in that time. It's not easy to ponder.
>
> Thanks for listening.
> hjh
>
> Sent with AquaMail for Android
> http://www.aqua-mail.com
>
>
>
>
> _______________________________________________
> sc-dev mailing list
>
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
> search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/


_______________________________________________
sc-dev mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/
Reply | Threaded
Open this post in threaded view
|

Re: Handling events that cross structural time points

Scott Carver
Though it sounds hard to implement CORRECTLY, in a way that could live in the classlib and be a good long-term solution ---- wouldn't this look something like:

1. Introduce a notion of "preroll" to EventStreamPlayer
2. Introduce a notion of an Event "relativeStartTime", which defaults to 0 but can be negative or positive for notes that should start just before or just after their scheduled time.
3. Modify EventStreamPlayer:prNext to request the next event (e.g. stream.next) preroll seconds BEFORE it's scheduled.
4. Modify EventStreamPlayer:prNext to actually PLAY the next event (playAndDelta) at (time + relativeStartTime) rather than (time).

This is going to add latency to any realtime data used in event generation - this is, afaict, not solveable without fundamental changes to Event. It would also be challenging to make sure all P___ classes that depend on some concept of global time (Penv comes to mind) are using the LOGICAL time, the time the event is supposed to be scheduled, rather than the current thread time. 

At the end of the day, the real requirement is that an EventStreamPlayer needs to schedule things SOME amount into the future to evaluate events before they're needed - since the relative start time of an Event is non-deterministic (or, only determined at the time when it's generated), this pretty much has to be done via some ad-hoc delta amount.

And, apologies in advance Ron, I'm not super familiar with the Conductor stuff, you might be doing these things / have thought of these things already. :)

- Scott

On Thu, Mar 9, 2017 at 8:08 AM Kuivila, Ronald <[hidden email]> wrote:
Hi James,

Here are a few random thoughts in response...

PatternConductor was a first stab at thinking about this kind of issue.
It is not right for the needs you describe but it might open a door.  The basic idea there
is to have the clock's  future action/event queue be a part of the eventstreamplayer itself.
This allows realtime "conduction" to be  implemented by altering the tempo of the PatternConductor's
private clock.

But, as you suggest, what we really need is a consistent model for additional layers of future action queues built
into the specification of the eventstream rather than the player.   I am having a hard time thinking this through.
On the one hand it might be added to the cleanup framework - so an event is left hanging waiting for change of
state from its parent eventstream.  But that sounds like a nightmare to implement....

Actually, Ppar's fiddling of delta might be a symptom of the basic structural issue.
Once you pass through Ppar there is no  possibility of changing the order of execution
of parallel event streams. So, contingent actions need to be held by the eventstream itself
before it is subject to Ppar's fiddling.  Or Ppar would do that for each of its clients.

Cheers,

RJK

> On Mar 9, 2017, at 10:16 AM, James Harkins <[hidden email]> wrote:
>
> Sorry in advance for what is to follow.
>
> I just literally threw my computer a couple of feet because I was working on the problem of sustaining musical events through a structural time point. I deliberately aimed so that it would land flat on a pillow, but... you get the point. A conceptual weakness in SuperCollider has now reached what is, for me, such a critical point that I couldn't get through a programming session without literally hurling my computer through the air.
>
> So. I'm organizing materials into phrases. The event stream *must* wake up at a phrase boundary to decide which phrase to play next. Because SuperCollider streams have no future, the content of the next phrase cannot be decided until the phrase boundary.
>
> So... what if a note starts near the end of the previous phrase, and needs to tie across the barline until the first sounding note of the next phrase?
>
> SC events work wonderfully if you know in advance how long the note should sustain. But if you don't know *right now* if the next note will occur on beat 2 or 3.25 of the next bar, things become inordinately complex very quickly.
>
> I have been working on this problem for literally two months, and I had almost cracked it tonight, when I ran into an unrelated problem with the technique I was using to debug the last problem, and... Really. No. Seriously. WHY IS THIS SO HARD?
>
> It's not a far-fetched musical requirement, but it's making me feel like a novice programmer.
>
> I apologize somewhat -- I realize this is 90% venting and there might not be any possible structural changes in SC that could make this less painful. But I'm really deeply discouraged. 2.5 years working on a live coding system and this one problem puts the whole project in jeopardy. It's really impossible to manage pitched material without ties over the barline. And I'm not prepared to accept that SC can't handle this.
>
> Beg pardon for asking for advice about my direction here, but I have nobody to talk to locally and I'm feeling lost. I'm not making music anymore, just struggling with these damn problems. I'm either almost through them, or I've been going down the wrong path for two years and I had better just throw away everything I've done in that time. It's not easy to ponder.
>
> Thanks for listening.
> hjh
>
> Sent with AquaMail for Android
> http://www.aqua-mail.com
>
>
>
>
> _______________________________________________
> sc-dev mailing list
>
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
> search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/


_______________________________________________
sc-dev mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/
Reply | Threaded
Open this post in threaded view
|

Re: Handling events that cross structural time points

daniel-mayer
In reply to this post by jamshark70-2
>So... what if a note starts near the end of the previous phrase, and needs
>to tie across the barline until the first sounding note of the next phrase?


You can define one or more Groups per phrase for notes to be tied.
First events of next phrase(s) can perform a release action for previous group(s).

For notes tied over several phrases or more differentiated release timing
more bookkeeping would be required of course.

Greetings

Daniel

-----------------------------
www.daniel-mayer.at
-----------------------------


_______________________________________________
sc-dev mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/
Reply | Threaded
Open this post in threaded view
|

Re: Handling events that cross structural time points

jamshark70-2
In reply to this post by Scott Carver

Thanks, Scott and Ron.

On March 10, 2017 04:40:38 Scott Carver <[hidden email]> wrote:

> Though it sounds hard to implement CORRECTLY, in a way that could live in
> the classlib and be a good long-term solution ---- wouldn't this look
> something like:
>
> 1. Introduce a notion of "preroll" to EventStreamPlayer
> 2. Introduce a notion of an Event "relativeStartTime", which defaults to 0
> but can be negative or positive for notes that should start just before or
> just after their scheduled time.
> 3. Modify EventStreamPlayer:prNext to request the next event (e.g.
> stream.next) preroll seconds BEFORE it's scheduled.
> 4. Modify EventStreamPlayer:prNext to actually PLAY the next event
> (playAndDelta) at (time + relativeStartTime) rather than (time).


This is not a bad idea. But you've also explained the two reasons why I haven't seriously tried to do it:


> This is going to add latency to any realtime data used in event generation

... including live-coding strings input by the user. I'm already finding that 200 ms latency is too large a window -- it's astonishing how often I would submit a new pattern and miss the boundary by a fraction of a second, meaning that the audience sees the change and hears it seconds later, rather than hearing it immediately. This is proposing to add a mandatory, unavoidable bar's worth of latency to that IO feedback loop... not quite workable for this use case.


> It
> would also be challenging to make sure all P___ classes that depend on some
> concept of global time (Penv comes to mind) are using the LOGICAL time, the
> time the event is supposed to be scheduled, rather than the current thread
> time.


Basically the clock needs to spoof a future time, but only when needed. I can't imagine right now how to do that cleanly.


hjh

Sent with AquaMail for Android
http://www.aqua-mail.com

Reply | Threaded
Open this post in threaded view
|

Re: Handling events that cross structural time points

Scott Carver
Actually, all of the functionality I described is currently part of Event. I swear, this is the LAST time I assume Event can't already do the thing I need it to do.....

\latency controls how ahead of time scheduling happens
\timingOffset can be negative, scheduling the event in the pseudo-past.

(
j = j ?? {
SkipJack({
~offset =  QtGUI.cursorPosition.x.linlin(0, Window.availableBounds.width, 0, -1); 
}, 0.05);
};
SynthDef(\ping, {
|freq, amp=1, attack=0, pan|
var env, sig;
env = Env([0.001, 1, 0.001], [attack, 1.5 - attack.abs], [8, -8]).kr(doneAction:2);
sig = LPF.ar(LFSaw.ar(freq, 0, amp * env), 1000);
Out.ar(0, Pan2.ar(sig, pan));
}).add;

Ppar([
Pbind(
\instrument, \ping, 
\degree, 3,
\octave, Pseq([Pn(3, 12), Pn(4, 8)], inf),
\dur, 0.25, 
\timingOffset, Ppatlace([
0,
0,
Pn(Pkey(\dur) * Pfunc({ ~x }), 1),
], inf).trace,
\attack,     Pkey(\timingOffset).neg.max(0),
\pan, -1,
\latency, 0.5,
),
Pbind(
\instrument, \ping, 
\degree, Pseq([0, 3, 5, 0, 2], inf), 
\pan, -1, 
\dur, 0.25,
\pan, 1,
\latency, 0.5,
)
], inf).play;

)



On Thu, Mar 9, 2017 at 4:51 PM James Harkins <[hidden email]> wrote:

Thanks, Scott and Ron.

On March 10, 2017 04:40:38 Scott Carver <[hidden email]> wrote:

> Though it sounds hard to implement CORRECTLY, in a way that could live in
> the classlib and be a good long-term solution ---- wouldn't this look
> something like:
>
> 1. Introduce a notion of "preroll" to EventStreamPlayer
> 2. Introduce a notion of an Event "relativeStartTime", which defaults to 0
> but can be negative or positive for notes that should start just before or
> just after their scheduled time.
> 3. Modify EventStreamPlayer:prNext to request the next event (e.g.
> stream.next) preroll seconds BEFORE it's scheduled.
> 4. Modify EventStreamPlayer:prNext to actually PLAY the next event
> (playAndDelta) at (time + relativeStartTime) rather than (time).


This is not a bad idea. But you've also explained the two reasons why I haven't seriously tried to do it:


> This is going to add latency to any realtime data used in event generation

... including live-coding strings input by the user. I'm already finding that 200 ms latency is too large a window -- it's astonishing how often I would submit a new pattern and miss the boundary by a fraction of a second, meaning that the audience sees the change and hears it seconds later, rather than hearing it immediately. This is proposing to add a mandatory, unavoidable bar's worth of latency to that IO feedback loop... not quite workable for this use case.


> It
> would also be challenging to make sure all P___ classes that depend on some
> concept of global time (Penv comes to mind) are using the LOGICAL time, the
> time the event is supposed to be scheduled, rather than the current thread
> time.


Basically the clock needs to spoof a future time, but only when needed. I can't imagine right now how to do that cleanly.


hjh

Sent with AquaMail for Android
http://www.aqua-mail.com

Reply | Threaded
Open this post in threaded view
|

Re: Handling events that cross structural time points

Scott Carver
Or rather:
(
j = j ?? {
SkipJack({
~offset =  QtGUI.cursorPosition.x.linlin(0, Window.availableBounds.width, 0, -1); 
}, 0.05);
};
SynthDef(\ping, {
|freq, amp=1, attack=0, pan|
var env, sig;
env = Env([0.001, 1, 0.001], [attack, 1.5 - attack.abs], [8, -8]).kr(doneAction:2);
sig = LPF.ar(LFSaw.ar(freq, 0, amp * env), 1000);
Out.ar(0, Pan2.ar(sig, pan));
}).add;

Ppar([
Pbind(
\instrument, \ping, 
\degree, 3,
\octave, Pseq([Pn(3, 12), Pn(4, 8)], inf),
\dur, 0.25, 
\timingOffset, Ppatlace([
0,
0,
Pn(Pkey(\dur) * Pfunc({ ~offset }), 1),
], inf).trace,
\attack,     Pkey(\timingOffset).neg.max(0),
\pan, -1,
\latency, 0.5,
),
Pbind(
\instrument, \ping, 
\degree, Pseq([0, 3, 5, 0, 2], inf), 
\pan, -1, 
\dur, 0.25,
\pan, 1,
\latency, 0.5,
)
], inf).play;

)


On Thu, Mar 9, 2017 at 8:12 PM Scott Carver <[hidden email]> wrote:
Actually, all of the functionality I described is currently part of Event. I swear, this is the LAST time I assume Event can't already do the thing I need it to do.....

\latency controls how ahead of time scheduling happens
\timingOffset can be negative, scheduling the event in the pseudo-past.

(
j = j ?? {
SkipJack({
~offset =  QtGUI.cursorPosition.x.linlin(0, Window.availableBounds.width, 0, -1); 
}, 0.05);
};
SynthDef(\ping, {
|freq, amp=1, attack=0, pan|
var env, sig;
env = Env([0.001, 1, 0.001], [attack, 1.5 - attack.abs], [8, -8]).kr(doneAction:2);
sig = LPF.ar(LFSaw.ar(freq, 0, amp * env), 1000);
Out.ar(0, Pan2.ar(sig, pan));
}).add;

Ppar([
Pbind(
\instrument, \ping, 
\degree, 3,
\octave, Pseq([Pn(3, 12), Pn(4, 8)], inf),
\dur, 0.25, 
\timingOffset, Ppatlace([
0,
0,
Pn(Pkey(\dur) * Pfunc({ ~x }), 1),
], inf).trace,
\attack,     Pkey(\timingOffset).neg.max(0),
\pan, -1,
\latency, 0.5,
),
Pbind(
\instrument, \ping, 
\degree, Pseq([0, 3, 5, 0, 2], inf), 
\pan, -1, 
\dur, 0.25,
\pan, 1,
\latency, 0.5,
)
], inf).play;

)



On Thu, Mar 9, 2017 at 4:51 PM James Harkins <[hidden email]> wrote:

Thanks, Scott and Ron.

On March 10, 2017 04:40:38 Scott Carver <[hidden email]> wrote:

> Though it sounds hard to implement CORRECTLY, in a way that could live in
> the classlib and be a good long-term solution ---- wouldn't this look
> something like:
>
> 1. Introduce a notion of "preroll" to EventStreamPlayer
> 2. Introduce a notion of an Event "relativeStartTime", which defaults to 0
> but can be negative or positive for notes that should start just before or
> just after their scheduled time.
> 3. Modify EventStreamPlayer:prNext to request the next event (e.g.
> stream.next) preroll seconds BEFORE it's scheduled.
> 4. Modify EventStreamPlayer:prNext to actually PLAY the next event
> (playAndDelta) at (time + relativeStartTime) rather than (time).


This is not a bad idea. But you've also explained the two reasons why I haven't seriously tried to do it:


> This is going to add latency to any realtime data used in event generation

... including live-coding strings input by the user. I'm already finding that 200 ms latency is too large a window -- it's astonishing how often I would submit a new pattern and miss the boundary by a fraction of a second, meaning that the audience sees the change and hears it seconds later, rather than hearing it immediately. This is proposing to add a mandatory, unavoidable bar's worth of latency to that IO feedback loop... not quite workable for this use case.


> It
> would also be challenging to make sure all P___ classes that depend on some
> concept of global time (Penv comes to mind) are using the LOGICAL time, the
> time the event is supposed to be scheduled, rather than the current thread
> time.


Basically the clock needs to spoof a future time, but only when needed. I can't imagine right now how to do that cleanly.


hjh

Sent with AquaMail for Android
http://www.aqua-mail.com