Creating a counterpoint object
Hi @oid. After reading your most recent post I think I am starting to get it and I can see the advantages to how you are approaching this. It seems you are modularizing parts of the patch. That's why it would be easier for me to envision this in C++ because i can have a different block of code for different situations. And of course you can get as detailed as you want in each section.
I am going to post what I have so far, even though it doesn't really work very well yet. In folder there is a patch called counterpointtest, and other necessary elements.
For now I am trying out the expr object with two variables. f1 is an incoming scale step, and f2 is an interval between the last two notes.
The patch should generate two notes. The one on the left would be a scale step a musician would input into the patch, and the one on the right would be generated based on some counterpoint rules that will be in the expr object (for now I only have a few to see how everything will work).
The inputs Into the expr are intervals based on a 7 note scale, starting with 0. So 0 = unison, 1 = a 2nd, 2 = a 3rd, 3 = a 4th, 4 = a 5th and 7 = an Octave.
In the f2 inlet of the expr should be the interval between the last 2 notes tested.
What should happen is when a new note is played it’s state of change is tested against the last note played
Ideally what would happen is I would play a note that would be f1, that note would be tested against the previous f1. For example, is the new f1 a scale step higher, or lower, etc. Whatever that difference in the past f1 to the current f1 would go into the expr object f1 inlet.
In the other inlet of the expr object, f2 would be the last interval between the two notes, so a 5th, 4th, 3rd etc.
A new interval should be generated by the expr object and added to the f1 scale step that was played. This new note will be played out of the right side of the patch., and the note selected to be played by the musician will be played on the left side of the patch, generating a two note interval (dyad).
This patch doesn't work so well yet. One reason is that I need to put in every possible combination of intervals and scale steps into the expr. Maybe this is crazy as there are probably a hundred possible ways 2 notes can interact. And on top of that I want some interval combinations to have several possible weighted outcomes. Maybe this is too much work, but If I could do it it might be cool to use.
Anyway, if anyone has time to take a look and let me know if I am approaching this in a way that might work and be practical.
thank you. Nick
Creating a counterpoint object
@nicnut [expr] outputs ints and floats, not bangs.
Also [expr] is tedious with complicated if-else statements, you have to nest them:
[expr if ($f1==1, 1, if ($f1 ==2, 2, 0) )]
or
[expr if($i1==1, 1, 0;
if ($i1==2, 2, 0) ]
But the object you are describing is [select] or [sel] in short.
Also right click in Vanilla on the blank canvas > help
to see all Vanilla objects
(this is the vocabulary)
and look closer at operators [==] [>] [&&] ect. also [moses]
To read some 'previous' data I usually do
[t f b]
X
[f]
this first outputs the previous float, then stores the new one in [f].
But if you may want to look further past, and make up more complicated rules, building lists or writing into [text] or [array] will be more flexible.
For probabilities, there are [array random] or [random] for example.
bytebeat and dynamic repatching, PD as a livecode environment
it's been done before but this was my take on a simple way to livecode with [expr] in pure data - it leans into being as simple as possible so its easier to take it and use it for something else (bytemidi, drum triggers, using [expr~] instead for rampcode(?)).
a thing c and [expr],[expr~] share in common youcanwritefunctionswithoutanywhitespace so there didn't have to be any messy patching dealing with that - as an example it's being used for bytebeat (with some caveats about floats and things that [expr] doesn't like like sending it 0 with [value] at audio rate. It's pretty easy to change up - for example - pick a new big number and small number to the [mod ]s and you can make triggers for a sequencer. you could modify it to be [expr~] by changing the [message< , could stack more livecode inputs to control other things like the update frequency. anyway
https://patchstorage.com/bytebeat-and-dynamic-repatching-pd-as-a-livecode-environment/
"this is an experimental way to allow dynamic repatching in PD and do livecoding just using pure data.
livecoding requires – 1) an obscure language – pure data is a dataflow programming language 2) an obscure text editor – well I cant think of a more arcane one than a visual programming language so check that off for pure data too.
Known limitations – it’s a little crashy – the List message box doesn’t like backspaces.
32 bit floats lose precision and can make it a seem a little wonky – not all patches will sound the same because Pure Data uses 32 bit floats for effeciency. so objects with / % >> will effectively “chop” off and the patch will sound different than a real bytebeat (or whatever you use this for) after a while or seem like it can just plain quit. The numbers either got too small or too big to work with 32 bit floats.
Another thing about 32 bit floats, the biggest number PD can count to is 1.6772e+07
Pure data also squashes numbers you get 123456 digits. 1234560 turns into 1.23456e+06. In comments this gets changed after you close, reopen so try cut/paste.
Also I noticed sending 0 into [expr] in the variables makes it unhappy and crash so I avoided it making x and y 1 or bigger.
Anyway – check out
to see it in action – and if you want o use this for something else remove anything connected before and after the spigot objects.public domain / unlicense / fishcrystals out"
pasting the same patch here: dynamicsinPatchingBYTEBEATeditionNewest.pd
dno about all the terminolgy and requirements, but it makes me happy when I see other people being creative and livecode has been a way to get people into doing experimental computer audio and video - probably after working where work is on the computer , personally I saw it as a way to rapidly prototype & it was my very first idea about something I wanted to do with bytebeat and pure data (only took a year! lol) - thanks to everyone in the community & the discord and netpd for making stuff and being helpful and being inspriring
extra backslashes appearing in Pd messages after save/reopen
Hi everyone!
I bumped recently into this difficulty and I am not sure if this is a bug or a feature: when I create a message with contents
;
pd-test.pd obj 10 10 expr $f1/$1;
pd-test.pd obj 110 10 expr $f1 / $1;
and I save and re-open this patch, the message reads
;
pd-test.pd obj 10 10 expr $f1/\$1;
pd-test.pd obj 110 10 expr $f1 / $1;
which is obviously interpreted differently because of the inserted backslash before the first $1. Apparently the space prevents Pd from inserting this backslash in the second line of the message. Is this the expected behavior? If so, is there a specification regarding escaped sequences and/or dollar signs appearing at the beginning or middle of symbols that explains it?
I would like to emphasize that my question refers exclusively to how PdFileFormat encodes and decodes Pd messages in general, and bears no relationship with the [expr] object or with dynamic patching (though the reference to them is obvious).
A follow-up difficulty has to do with the internal representation of the first message in the saved file, which is:
#X msg 10 135 ; pd-test.pd obj 10 10 expr $f1/\$1 ; pd-test.pd obj 110 10 expr $f1 / \$1 ;;
where Pd interprets the backslash in the symbol $f1/\$1 as an independent character. On the other hand, when I duplicate this message in Pd, the internal representation for the 2nd copy becomes
#X msg 10 135 ; pd-test.pd obj 10 10 expr $f1/\\\$1 ; pd-test.pd obj 110 10 expr $f1 / \$1 ;;
denoting that an independent backslash character would require to be backslash-escaped in the PdFileFormat. The fact that these two latter versions (with \$1 and \\\$1 in the file) appear and behave the same in the patch also struck me as unintuitive, so if anyone may shed some light into this I'd really appreciate.
Thanks in advance for your help!
Doing expressions without expr~ (compiling to heavy)
I have an expression 'heavy' patch I was hoping to convert via Heavy to Owl but it has fallen at the first due to the use of expr and expr~. I was wondering if anyone could help with the first few and then I could try and get my head round the others.
expr~ ($v1<.5)$v1; ($v1>=.5)$v1 splits waveform in two.
expr pow($f1, 1.0/3) power without pow?
expr~ $v1*((.5-$v2)/$v2);(-1*$v1+1)*((.5-$v2)/(1-$v2)) is totally beyond my little brain at the moment too!
None of this urgent or anything, just having fun.
Do you know how to dynamically write the function to an [expr]?
Thank you, @Jona and @whale-av for the pointers.
Yes. I want to be able to change the operators, etc. . So for instance the multiply in [expr $f1*$f2] to a plus while the Gem stream is running.
Two options I have tried are assembling an expr clone with all of its operators as type-selectable by idx, so an expr router of sorts. Where one could assemble the pieces by list(functypeID#) and variables. But that fails because it's just too clumsy.
The option below is the best, I've come up with so far.
And if, as you say whale-av, the expr itself is written at runtime (until the feature gets added sometime in the future ) probably the best way to go.
Should say something, I learned there is no way to pass it in as a symbol [expr $1`], where $1 is a creationarg symbol because expr interprets it as a desire to create an array.
One option may be using iemguts and dynamic patching. If I look into it, will try and let you know what I find out.
Seems sending it a list is something that should be added.
Would help a lot for patches where dynamically changing formulas in real-time streams (like a GEM or ~) best suit their design.
Thanks, again, @jona and @whale-av. Really appreciate your response and the timeliness with which you replied,
Happy PD-ing.
Here's the way I will probably go with: Popping the subwindow where all the expressions are then closing it when I'm done,
Do you know how to dynamically write the function to an [expr]?
@svanya You can pass = < | > etc. as arguments to an abstraction....... and therefore into the clones within [clone]....... and use them within [expr].
The problem is that for clones they are always the same, apart from as you say $1.
So you can only create one [expr] from the "extra" arguments.
Because [expr] is an object that can only happen at creation time.
So the answer is that you can set the [expr] for all clones...... but not per clone.
I think you would have to place all the expressions you might want within the abstraction and then [route] the internal data through the desired [expr] using $1.
Of course you can create the set of [expr] 's to choose from using the clone arguments if you wish..... a bit messy and unnecessary though.
David.
Logarithmic glissando
I think using the built-in objects should be slightly more efficient for the basic cpu usage at least (dunno about memory usage or how that might influence cpu usage tho) since [expr]
implements its own call stack and uses a switch/case for every operator in every computation (whereas the single-function objects follow pointers to functions in classes). not sure how much more or less efficient that is.. of course [expr]
is also far more convenient and clean from a language perspective.
tho btw, there is also a JIT expr compiler/external that should be just as fast if not faster than the vanilla many-objects approach
https://www.mail-archive.com/pd-announce@lists.iem.at/msg00234.html https://github.com/x37v/jit-expr
@bocanegra I thought that expr could be included in libpd and such now since the author permitted a license change. also since [expr]
is in vanilla those functions will be loaded no matter what (the expr class owns those functions, not the object. And the class is loaded when pd starts)
edit: after testing it seems like the equivalent objects are 1 1/2 - 2 times faster than [expr]
I don't understand \[fexpr~\]?
@Obineg [fexpr~]
is quite a bit less efficient than [expr~]
so, if you don't need per-sample memory or feedback it is much better to use [expr~]
why? because in order to store each of the output samples for the current processed sample, [fexpr~]
needs to operate on single passes of the perform loop, then store the input and output samples.
I think since [expr~]
deals with a block (vector) of samples it is generally more efficient since it can pipeline and vectorize the actual instructions. And it's not possible to do that if the next output sample is dependent on the current output sample.
plus, due to the way pd uses the input and output samples in a dsp graph, the input and output buffer might be the same buffer. This means that if you want to read an input sample from the past you first have to store it somewhere to make sure it won't be overwritten when writing to the output. so [fexpr~]
also has to do that when [expr~]
doesn't (since [expr~]
only processes input samples as a vector).
basically: [expr~]
operates on the whole vector/block (meaning the constituent functions/operators are applied "at once" over the vector/block for every part of the computation), [fexpr~]
operates on the individual samples of that vector/block. (meaning the constituent functions/operators are applied in turn to every sample in the block, one at a time, for every part of the computation)
[expr] logic problem – why is it doing this?
So, I'm working on a patch that is supposed to trigger a sound file to play on the hour and on the half between a specific start and end time.
I'm getting the time using zexy's [time] object. I'm then feed that into an [expr] object that's performing some basic logic to determine if the current time is between the specified start hour and end hour for playback, and either at the beginning of the hour or the beginning of the half hour, and the seconds are equal to zero. If all these conditions are true, the [expr] object outputs a 1, which then triggers the soundfile to play.
This expression looks like this:
expr if(($f1 >= $f4 && $f1 <= $f5) && ($f2 == 30 || $f2 == 0) && ($f3 == 0), 1, $f1)
where:
$f1 is the current hour
$f2 is the current minute
$f3 is the current second
$f4 is the start hour (this is currently set to 12 – i.e. noon)
$f5 is the end hour (currently set at 18 – i.e. 6pm)
It works perfectly. However, if $f1, $f2, $f3 are values like 1, 29, 32 (that's 01:29:32 in 24 hour time), the [expr] gives me true when it should be false! 01:29:32 is not within the specified start or end hour for playback.
I can't figure this out at the moment. I'm wondering if someone can help point out what dumb mistake I'm probably making.
Thanks