gen issue clarified and restated

brendan mccloskey's icon

Hi
perhaps a double post; but then again perhaps not, I think clarification and simplification is needed - it always helps.

Max Patch
Copy patch and select New From Clipboard in Max.

I now understand how and when to correctly implement a sah operation inside gen. But, the use of a delay offset appears to be messing up my timing for control signals to sah. If you have used gen successfully in your work, or have a deeper understanding of audio DSP than I, please have a look at the tiny example patch below, and thanks. No matter what algorithm I use, it always comes down to "no pitch modulation" or "no clicks" never both }: (

Brendan
thinking of changing my handle from n00bmeister to genSlave....

brendan mccloskey's icon

...fwiw, bypassing the sah (size into *0.5 into mstosamps) appears to place the discontinuities at the top of the window; returning to sah places them at the bottom...? I realize that scope~ is ill-suited to observing stuff at the sample level though.

davidsmith's icon

Hi - I'm definitely no gen expert but I took a stab at it as a learning exercise. I ended up duplicating the unshifted voice to see what the differences were. I could be wrong but it seems like using the same sah for both phase-shifted and unshifted ramps is where the clicks and the pitch problems lie... maybe this will be helpful!

5042.Untitled6.maxpat
Max Patch
brendan mccloskey's icon

Hi David
thanks for taking a look at this - this appears to work exactly as I need. You've saved me many sleepless nights mate, cheers, I've really been stuck on this for weeks,

all the best
Brendan

brendan mccloskey's icon

Still some overlap problems though, the phase shift is now tied to both ramp duration and mute duration, it should just be a function of ramp duration; apologies for not being clearer, but I'll try your suggestion and see if I can tweak it

thanks again

edit

that may have sounded dismissive, apologies. What I found is that the trick of changing the min/max values of the second [accum] object is clever, but that offset is fixed or rigid. What I hope to do is allow that offset to always be 50% of grain ramp size, irrespective of interonset value. I'll hack away at this today and return later.

Thanks again mate

Brendan

davidsmith's icon

Didn't find that to be dismissive at all!
I realized this am that the min max values was a problem. If both the accums were reset at the same time the phase relationship would change.
Changing the accum to a + .05 -> modulo 1. works, and you can reference the unshifted ramp from it's output. (or from the mute ramp which is resetting the 'phase' of the main ramp).
Hope this helps! it seems like its on the right track anyway..

5046.Untitled6.maxpat
Max Patch
brendan mccloskey's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Hi David, yes, % is another solution. Sadly, as I was putting together an annotated description of the issue as I see it and my anticipated goal, I revealed a fundamental flaw in the algorithm I'm using (mine, not leafcutter's or Peter's or etc) - it is that, when using a central phasor to drive everything in this way, pitch modulation in the shifted grain is unavoidable. Unavoidable. The patch below demonstrates this:

Thanks for your input everyone; apologies for not clarifying this before posting :(

Depressed. Whiskey. Failed PhD

davidsmith's icon

maybe stick to just the whiskey!

man i don't know if im fundamentally missing something, or just not hearing the artifacts, but I tried just duplicating the entire voice with ONLY the + modulo shift and it seems to be ok. If that works, maybe u could just make an unshifted voice and poly~ that with only the + object changing.

here u go:

5047.ohno.maxpat
Max Patch
davidsmith's icon

:( that one just doesn't work, but shouldn't it? giving up for now...

brendan mccloskey's icon

Hey thanks for taking part - some welcome insights!

As I demonstrated above, pitch modulation in the shifted window is unavoidable in a simple MSP version - the frequency calculation is done at the inlet to phasor ONLY, and that ramp is then shifted, so there's no opportunity to sah the offset freq via the new ramp. I think.

Compromise. It is only rapid fluctuation in ramp duration signal that exhibits clicks in the shifted window (pitch mod here is sorted); so I just threw a lowpass filter at the signal input. Do rightly!
:)

Brendan

leafcutter's icon

Not sure if/why you are avoiding gen~ but I think this may do what you need?

Max Patch
Copy patch and select New From Clipboard in Max.

Don't let the duration hit 0 or it will stall!

Max Patch
Copy patch and select New From Clipboard in Max.

This is quite a fun patch:

brendan mccloskey's icon

hi leafcutter

I have definitely caught the gen~ bug, thanks to you!

The patch at the top of this thread should describe the following: I'm shifting the mutable phasor to generate an overlap fixed at 50% of the ramp duration, regardless of mute duration, this much is done. The problem presents itself as clicks or pitch mod in the shifted grain (no such artefacts in the unshifted grain). I've tried every combination of sah and history, triggered by both/either ramp to no avail.

I'm looking forward to deciphering your new patches (in the morning) and I'm hoping, with the info already given by yourself, David, Peter and Graham

that I can finally put this to bed.

Lessons learned:

[1] don't split one problem between two threads
[2] define the problem in the simple terms possible
[3] buy every single book on music-and-maths

Best regards
Brendan

leafcutter's icon

Ok, I may have slightly misunderstood your question. Still I'm enjoying playing with my second patch!

brendan mccloskey's icon

Do you think the first patch in your example above be easier to adapt to my stated needs? I'm always going to run into the problem of unwanted pitch modulation when varying the frequency of a shifted ramp. This much is clear. And the only solution to that problem is to use two phasors, as in David's suggestion above, but that still leaves me with the challenge of correct application of sah and feedback triggers.

Thanks also for the demonstration patch using [sample]. I guess ultimately I'd like to run as much of this inside gen~ as possible, to avoid timing issues between gen~ and MSP vector size.

Brendan

Graham Wakefield's icon

I was thinking about this some more, and it occurred to me there's another problem. Say there are two ramps A & B which are 50% out of phase. Avoiding pitch wobbles is done by only sampling the duration at the start (or end) of the ramp. But if the duration changes between when A starts and when B starts, then they might drift out of 50% phase with each other. Or if B is always slaved to A, then B might get the pitch wobble/spike problem.

So I figured a solution would be that B only starts (and samples the duration input) when A passes 50% phase, and A only starts (and samples the duration input) when B passes 50% phase. They effectively ping-pong each other, with neither master or slave (which appeals to my sense of balance). A & B end up looking pretty much the same, and there'll be a history feedback going each way between them.

I'm on a cellphone currently so I can't patch this up now, but I suspect this could be the solution you're looking for.

brendan mccloskey's icon

Hi Graham
you have precisely described the problem I have been struggling to even vaguely communicate: in a master-slave algorithm, with the sah storing the frequency value of the master, the slave will exhibit unwanted pitch variation during frequency changes. [+ 0.5]--->[% 1] is the usual phase-shift trick, but as I am using an interonset signal as well, it seems that [delay] (and gen~) is my only recourse - which is where my woes begin. If you can be arsed tracing this thread, Peter McCulloch provided a solution to the clicks, and David Stevens also provided one solution. And I'm hoping that the original author of the gen code (leafcutter) is also scratching his head over this one.

Pint?

Brendan

jvkr's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Allow me to approach this problem from a completely different angle.
This idea is based on a grain-generator triggered by pulse, which, when busy, hands this pulse to the next instance. Generating pulses at a rate of 250 ms and setting grain duration to 500 ms will automatically create two grains out of sync by half the grain size. Does this work for you?

leafcutter's icon

This works pretty well there are still a few things to iron out but I got to get on with my own work now!

Max Patch
Copy patch and select New From Clipboard in Max.

`

brendan mccloskey's icon

@jvkr

a new approach to a stagnant problem is always welcome; I had thought of train~ in the early stages of this project and I knew gen~ would have to be involved which is why I didn't go there (gen~ n00bness). I'll have to ensure that I completely understand how/why your patch is doing specific things before I try to dissect and adapt it - thanks

@leafcutter
this does work better than my/our previous efforts - David's adaptation of your original works well too, via + 0.5 ---> % 1.

Clicks persist though. I'm going to use the most stable iteration of your original and then polyphonize it instead of shifting and shifting and headaches and headaches. I need to move forward too ;)

Best
Brendan

davidsmith's icon

Hi again - I haven't had time to look @ the other patches posted but i *think* I've managed to get a clickless and immutably shifted cycle going.

Part of the problem (in this version anyway) was that changing the mute amount caused the mute ramp to retrigger only when the change was happening from 0-1 but not if changing from large to small (i.e.. 1 to 0). This is where the clicks happened...

I'm not sure how to implement the play~ portion and I'm running out the door but here's what I have so far.

Sorry if this has been covered in previous posts

cheers

5055.clicklessshifted.maxpat
Max Patch
brendan mccloskey's icon

David
your input has been invaluable and I really appreciate your work on this. I have something REALLY nice here now and I'll investigate your latest patch to see if it surpasses your other excellent suggestions. If so, it will make this granulator I'm working on even sexier.

Guys, i consider myself the average Maxer, and I've been sweating over this problem for at least a week now, so I appreciate that solutions aren't just assembled in ten minutes, so thanks everyone - citations logged!!

Brendan

brendan mccloskey's icon

ps reading my previous entry, does "gen + n00bness" = "g00bness"

LOLZ

Ursine's icon

Reading up on this thread and very curious to see where all this work lead to. Brendan, can you link to your finished patch by any chance?

brendan mccloskey's icon

Hi ursine,
I'm afraid I have had to cease development of Granary, due to oppressive financial constraints. My audio work centres on PD and Supercollider atm but I hope to return to Max in the near future.

I can point you to the latest version I posted, about halfway down this thread (dated Nov 08 2015):
https://cycling74.com/projects/granary-a-hybrid-granulation-engine

People are still using it, messing with it, creating plugins etc, so if you search for "granary" on this site or on Ableton's forum, you might find more recent versions by other people

HTH
Brendan