Tidal Cycles, for example.
I’ve seen several simpler DSLs. I remember some code with strings using in “.” and “_” and nothing more.
Maybe we could make a list with examples
Tidal Cycles, for example.
I’ve seen several simpler DSLs. I remember some code with strings using in “.” and “_” and nothing more.
Maybe we could make a list with examples
That would be very cool… perhaps quite a grand project though.
… I wonder if we had an FFI you could just launch tidal cycles from within supercollider and communicate with it… (probably another thread!).
I havent said, you should use a DAW instead
I just think that DAWs are more easy to use to create formal structures. use what you want
With patterns variation is simple but goal driven development of formal structures couldnt be much more difficult.
I dont know if you are familiar with the midi tools which are available in Live 12.1.
To come up with variation in a DAW couldnt be more easy nowadays.
The practical guide to patterns is really good, and I’ve got a lot out of it. I do think that some of it could be directly linked to from the class documentation - might sound redundant but I would find it useful, as when I’m searching documentation I always look at the class documentation first. Idk… a lot of it is probably user error on my behalf, and I’ve mostly managed to get the answers I’m looking for, but some of it has taken some hardcore forum diving.
it’s regrettable that it cost you so much time to find that out, but the information was actually there – just poorly indexed, I guess.)
I used the .next(()); example for Pbind specifically because the class documentation says this, as the first example:
(
a = Pbind(\x, Pseq([1, 2, 3]), \y, Prand([100, 300, 200], inf), \zzz, 99);
x = a.asStream;
)
x.next(()); // pass in an event ()
x.next(());
x.next(());
x.next(()); // end: nil
this is exactly the answer I was looking for, but could be better signposted with “in comparison to calling next on an eventstream, this is how you do it on Pbind” - or whatever the correct technical specification is.
There are lots of other examples in the documentation like this. I just looked up Plazy
and there is basically no way you could work out what the class does from the documentation if you were a beginner imo (I learned how the class works from one of Eli’s pattern tutorial videos).
You would need ghci (haskell interpreter). it works sending osc messages to sclang
But I guess you also meant that sclang could have a good parser combinator. With that leverage, I could see a lot of possibilities for merging patterns and DSLs.
Supercollider would greatly benefit from a library equivalent to Parsec and others.
Parsec does not have a concept of tokenization. It just works like building Lego. It fits what we do way more than old-style tools used by ScDoc (bison, lexer, etc).
My goodness so much of this resonates with me! In particular, the bit about the difference between Event, Stream, and Pattern (including the need for .next(())
). I also strongly agree that the default \amp
value of 1 would be a good call.
If I could throw my own two cents in, I think the following would be quite useful to the general userbase:
\dur
is often such a crucial unifying factor in writing parallel Pbind
style patterns, some kind of composition method that doesn’t necessitate writing a separate Pattern
type in another variable and re-referencing it multiple times would be great.Event
types, if that sort of thing is possible<>
for Pchain
would be great syntactic sugar/time saving. One particular place this comes to mind would be for Pbindf
Thanks for inquiring. Excited to see what developments come!
Correct me if I’m wrong, but I think that Pbindf
can always be replaced with Pchain
and is therefore entirely redundant:
(
a = Pbind(\degree, Pseq([1, 2, 3], inf), \dur, 1);
b = Pbindf(a, \detune, Pseq([-30, 0, 40], inf), \dur, Prand([0.2, 0.4], inf));
c = b.asStream;
)
c.next(())
is really the same as
(
a = Pbind(\degree, Pseq([1, 2, 3], inf), \dur, 1);
b = Pbind(\detune, Pseq([-30, 0, 40], inf), \dur, Prand([0.2, 0.4], inf)) <> a;
c = b.asStream;
)
c.next(())
Unfortunately, the help file does not mention this at all…
The reason for the default is to provide headroom for mixing. I think we should not eliminate headroom from SC’s default settings.
If it’s really felt strongly that events’ default amplitude should be 1, then I’d suggest to compensate by reducing the the server’s default volume by, oh, 12 dB or so…? I’ve always tended to work at about -18 dBFS (my current practice is, event amp = 0.5 ~= -6 dB and mixer channel volume = -12 dB, adding up to about -18) and when I post code examples here, almost always do a * 0.1
at the end of a synth so as not to blow anyone’s eardrums out.
hjh
I think you’re probably right about this on second thought. Despite my comparison before, I realised Ableton does do this in a way: by setting the velocity scale value on most instruments, and making default midi clip velocity 100.
Should we soft deprecate Pbindf
? Perhaps by just mentioning this in the help file?
One of the reasons patterns are complex is due to the vast number of Pattern objects to learn and to search through.
I think so. Pchain
resp. <>
is definitely the more general solution.
@jamshark70 Am I right that Pbindf
can be always replaced with Pchain
? Or do you know of any differences in behavior?
I get your frustration, Dindoleon. I had been using SuperCollider for a while before I noticed that there is a very convenient way to specify multiple event keys from a single pattern when defining a Pbind. For example:
(
Pbind(
#[degree, dur], Pseq([[0,2],[3,1/2],[4,2]], inf)
).play;
)
Couple small thoughts: It can be hard to find the right pattern or remember the names. We have Pbindef and Pbindf, Pser and Pseries etc. Longer names might be helpful - Pbind PbindMono PbindArtic - or flags could group silimar functions - Pbind( arrayOfPairs, mono:true)
. aside: It would also be nice if Pbind, Pmono and PmonoArtic had the same number of arguments! The P
as a sort of pseudo-namespace is either too much or not enough depending how you look at it!
Put another way, could the library not be more clearly organized?
Regarding the default Event I really wish that it were necessary to opt-in via the type
key! If ().play
produced nothing and users had instead to do (type: \note).play
to hear sound it would really help new users! Beyond that there is something sort of offensive about assuming that type here as all kinds of musical decisions are promoted as normal. I would rather see a more open neutral frame!
Nice!
This syntax is rather esoteric though… automatically promoting literal identifiers to symbols when in array literals is seldom used, and perhaps a little confusing — the Pbind
help file is one of the few places it is mentioned.
You can also write it like this…
Pbind(
[\freq, \dur], Pseq([
[0, 2], [3, 1/2], [4, 2]
], inf)
).trace.play
(I didn’t know this before today!)
@semiquaver are you talking about reorganising the help files into better hierarchies? Or something else?
Perhaps we could all come up with a list? I dislike Prout
, it stands for Proutine
, its three more letters and is much clearer — I always read it as ‘Pattern’ ‘r’ ‘out’ and wonder what the ‘r’ stands for.
To implement this renaming, the only way I can think is to do this…
Proutine : Whatever {
.... old body of Prout ...
}
// This is the old name of Proutine, do not extend this class, use Proutine instead.
Prout : Proutine {}
Not the nicest, but could work, would be good to hear any objections before going ahead and agreeing on some clearer names.
For a different, fully stateless approach to patterns, Martin Gius and I are working on an implementation of a dialect of tidalcycles in sclang and haskell. It is called Zwirn aka nth, and here is the – very unfinished! – repository: Julian Rohrhuber / nth · GitLab. It has a hackable library of functions that operate on patterns.
Here, you make patterns in which you index with an arbitrary time value and you are returned values for that time. Of course, it lacks the nice behaviours of streams!
With Pnth they can be integrated with the usualy event system. But you can also index with a UGen in a synth graph (the idea is that it should work the same in sclang and scsynth).
~plot.(~fast.([1, 2, 3, 4], [4, ``[5, -4, 10]])); // the factor can multichannel expand
You can just call integrate
on a pattern, and use moddif:
Pbind(
\dur, Prand([1, 0.25, 0.5], inf),
\isOnBeat, 1 - Pkey(\dur).integrate.moddif(0, 1)
).trace.play
(this guy’s channel is great, btw)
Id really like to see your routines and the way you make vertical rhythms. Thanks