Creating GRM Tools shuffle for Max/MSP
I am writing a copy of the shuffle program in the GRM Tools library, with a view to expanding it to 8-channels. I have got a basic patch going, however quite large clicks are generated when I increase the delay. When it is at zero everything is fine. I am 90% sure it is an issue with the tapein~ -out~ combo as when I tried the patch without these objects the problem vanished...
Any suggestions are much appreciated.
Regards
Chris
The main poly~ patch is below - if anyone is able to have a look at the complete patch I can send it your way.
HI Chris,
Haven't tested this but a few quick questions...
1 - Why the speedlim and why drive the tapout~ with a signal when the delay will stay the same for the duration of the grain. I'd lose these objects and drive the tapout~ directly with a float value.
Wait - I see this is going to eventually transpose - you will need a sig~ driving tapout~ to do that.
2 - Are you running your scheduler in audio interrupt? If not, do the clicks improve when you do (assuming you've taken out the sig~ and the speedlim as mentioned above).
I don't think your mute / busy method will work totally reliably if you are not running the scheduler in audio interrupt. I think a better solution would be to do the following.
On receiving a not message set the poly busy (but not the DSP on) - so the right output of your trigger.
Then - set all your other values for delay, panning, whatever
Finally set DSP on
Ahhhh- wait - I remember this - I made a transposing granulator realtime patch with poly~ this summer and the issue you are having is probably a combination of scheduler/audio timing and tapin~/tapout~. What I did was have DSP on in the poly~ all the time so that the tapin~ is always working (filling the delay buffer) - that way you can lose the annoying delay/bondo stuff and take your grain finished bang straight off your line~ driving the window. This way you don't get clicks in the tapin~ buffer due to it turning on and off....
That would all look like this: (I think it should work, but I've just done it in 30secs so....)
If you get stuck any further, especially on the transposing delay thing (which I seem to remember was a little bit gnarly to work out let me know and I'll post up my patch (which I don't have on this computer right now) - which does pretty much exactly the same thing as you're doing here, with transposition...
REgards,
Alex
Hi,
you might like to take a look onto the shuffler I created some time ago.
You can download it from the homepage of my research center ZiMT:
> English
> Downloads
> Shuffler
Enjoy,
best wishes,
Johannes
www.johanneskretz.com
Cheers Alex - that is much better (and more importantly, simpler!). The only change I made was to put the del object back between the left-hand trigger bang and the rchoose for the grain duration. That way the arrival of the grain is delayed by the same length as the incoming signal, providing some much loved random variation, as well as preserving the alignment of the grain and delayed signal.
And yes - the pitch control will be a tough beast to crack. Time to put my maths head on.
All the best
Chris
"What I did was have DSP on in the poly~ all the time so that the tapin~ is always working (filling the delay buffer"
havn't been looking into this closely, just the above caught my eye:
i would suggest leaving the [tapin~] object outside the poly~ (having only one instance of it in the main patch) and to work with a send/receive connection to the [tapout~]'s inside the poly~. as this is not a signal connection, but just a reference to internal memory, there are no problems with differing sigvs etc.
this way you can still mute the poly instances and still have the delay memory fill constantly.
volker.
@volker - I was thinking about that, but I don't believe it's good practice to do this - can you confirm that it works with differing vs inside and outside the poly? - my guess would be that you will get problems.... I can't think how the design of the object could possibly be such that it would work under all circumstances - but of course I may be wrong....
@chris -
"The only change I made was to put the del object back between the left-hand trigger bang and the rchoose for the grain duration. That way the arrival of the grain is delayed by the same length as the incoming signal, providing some much loved random variation, as well as preserving the alignment of the grain and delayed signal."
I don't think you need to do this - if you want random variation of some sort I'd do it differently - there is no need to align the grain and the the delayed signal - when you change the delay on a tapout then the delay changes instantly - the delay buffer is already full - so you start reading out samples from N milliseconds previously (which are already there) - all you are doing by "aligning them" is delaying your grains so you get N milliseconds of silence before the grain starts - this may seem counterintuitive but you are not delaying an event (as in the max delay object) - you are reading from a buffer which is already there - hence leaving dsp on in each poly~
Alex
Good stuff, I've been trying to replace a lot of my vsts with msp equivalents.
@ volker - ok I just tested and as I suspected mixing a tapin~ outside a poly~ with a tapout~ inside a poly~ of a different vs results in incorrect functioning, so I wouldn't advise this - it *should* work with a poly of the same vs but it's always safe to have tapin~s inside the poly - I don't think the cpu stuff should be too much of a consideration - there are likely other ways to achieve dynamic cpu usage anyway...
Alex
I can confirm that having tapin outside of a poly won't work. What you can do to preserve cpu usage is to have have all your signal processing objects, except in~ and tapin~ and your out~(s), placed in a subpatch in the poly~ abstraction and then connect a mute~ object to that subpatch. You then send a 1 or 0 message to the mute object according to the instance's busy state.
Here's an example of a poly~ patch which also uses variable delay to alter the pitch of a grain.
Hope it helps.
T
@alex - yes, might very well be, that with differing sigvs you run into trouble. haven't tried that.
so, if you want to be on the safe side, stay away from those "send/receive into poly~"-affairs.
v
@Terry McDermott - to be totally clear on this I can get a tapin~ to link to a tapout~ when the tapin~ is outside the poly and the tapout~ inside. That does not seem to be a problem - you can either connect via send/receive (as volker suggests and is probably safer than any other method), or, if you use an inlet of the poly you will need to make sure that you set target 0 to the poly before audio is switched on (every time) - this second method is likely to be problematic to code effectively and neatly and if you anyway uses this trick I'd suggest the send/receive method.
If your poly has a different vs or uses upsampling or downsampling you'll more than likely run into issues so I wouldn't do that. Otherwise it comes under one of those tricks I would use with caution only if you really want to and you're sure of what you're doing - if not get your tapin~ inside the poly......
A.
I am using a construction with tapin~ outside of the poly~ and the corresponding tapout~s inside all the time since years. It is perfect, as you really access the same buffer~.
It is much less about CPU, its about memory, as each tapin~ would eat up its own memory. I have a 90 seconds delay and 32 voices. With one tapin~ I need roughly 15 MB, 32 tapin~s would eat almost 500 MB. That does make a big difference. And as Volker mentioned already, you can mute the voices without problem, if you would mute the tapin~ it would stop recording...
I don't see any disadvantage, its safe, and if you change your sampling rate in the poly~ you will even get a warning...
Stefan
I'm going to start doing this for my multitap delay.
Alex,
Ok i must have done something untoward-- I'll revisit my "tapin outside poly" patch-- maybe it was a vector size or sample-rate issue as you suggest-- but I do remember getting discontinuites in the tapped signal. I'll try the send/receive method as Volker outlined.
T