hmm, yeah, I hadn't checked the values, well, I'm now thinking it makes better sense to set the above value randomly
-
looking for velvet noise generator
-
@manuels said:
By multiplying the frequency with 1/SR you get the phase increment of the phasor. Since there is exactly one sample in each cycle where the sum of the current phase and the increment gets bigger (or equal to) 1, you get the impulse. Now all you have to do is to randomize the phase to get the impulse at a random position.
Just realised, that I didn't consider one important thing here: If the period isn't an integer number of samples, then the method of adding a random number and wrap doesn't work anymore!
-
yeah, it can't get simpler than this, I guess it can be more sophisticated, to never miss a period, but I also think this is a job for a C code.
-
I need to make [pimp~] multichannel, then I will also adapt it to become [velvet~} and it'll also be multichannel, meaning it can receive a multichannel signal to set different frequencies and it'll output a multichannel signal with independent impulse generators.
[else/dust~] and [else/dust2~] are already multichannel, so [velvet~] must also be to follow suit
I'm releasing ELSE RC12 soon, this will hopefully be part of the next RC13 update
-
@porres said:
to never miss a period, but I also think this is a job for a C code.
To atone for my earlier SC jibe, here's a delay-based approach. (Also, indeed you're right -- I hadn't read the thread carefully enough. Dust / Dust2 don't implement exactly "one pulse per regular time interval, randomly placed within each interval.")
Uses else's del~ because delread~ requires a message-based delay time, which can't update fast enough, and delread4~ interpolates, which smears the impulses. With del~, I could at least round the delay time to an integer number of samples, and AFAICS it then doesn't interpolate.
It looks to me in the graphs like there is exactly one nonzero sample per phasor~ cycle.
hjh
PS FWIW -- one nice convenience in SC is that non-interpolating DelayN doesn't require the delay time to be rounded
( a = { |density = 2500| // var pulse = Impulse.ar(density); // for similarity to Pd graphs, I'll phasor it // but the Impulse is sufficient for the subsequent logic var phasor = LFSaw.ar(density); var pulse = HPZ1.ar(phasor) < 0; var delayTime = TRand.ar(0, density.reciprocal - SampleDur.ir, pulse); var rand = TRand.ar(-1, 1, pulse).sign; [DelayN.ar(rand * pulse, 0.2, delayTime), phasor] }.plot; )
-
@ddw_music said:
PS FWIW -- one nice convenience in SC is that non-interpolating DelayN doesn't require the delay time to be rounded
I could include a -nointerp flag to del~ so it does that too
-
@ddw_music you can just use [rint~] or other objects instead of the [trunc~] approach
-
I do think @manuels original idea of having a sample-increment offset still works without missing periods?
Why don't you think it works with non-integer period lengths?a phasor~ is always guaranteed to have its last sample be within the last sample increment regardless of whether an integer-period or not, and
[wrap~]
will pretty much perfectly wrap the phasor~'s phase.. -
I adapted the delay patch (and made other improvements, removed unnecessary stuff) with more ELSE objects, since it's in plugdata and uses del~ anyway... one can just use [imp~] instead, but [pimp~] is used to print the phase.
I was wondering about this approach and I wonder what happens if the frequency keeps changing drastically at signal rate... my intuition tells me it might go bad!
What I didn't like about this approach is also having a delay limit that limits the lowest frequency possible.
-
@porres here's what I mean about adding parameters for bias/regularity
if you set regularity to max and polarity one extreme or the other it's an aliased pulse train
velvet-controls.zipsome of the papers were mentioning it, you can get some cool effects
-
some of the papers were mentioning it, you can get some cool effects
if they were mentioning, that changes everything and yeah, that's what I thought about the polarity... and the regularity is something I actually find interesting now that I see it...
hmmmm, I guess I can add them too in my version thanks
-
which papers exactly? can you post them again? I guess it's time to read it
-
@ddw_music said:
Uses else's del~ because delread~ requires a message-based delay time, which can't update fast enough, and delread4~ interpolates, which smears the impulses. With del~, I could at least round the delay time to an integer number of samples, and AFAICS it then doesn't interpolate.
Actually delread4~ doesn't smear if the delay is always an integer number of samples (which makes sense from the cubic interpolation formula -- if the fractional part of the index is 0, then you just get the sample value at the integer index).
It's easier to ensure an integer-sample delay time using else/del~'s -samps flag
I've definitely not dug deeply enough into ELSE -- so many things that are a PITA in vanilla become straightforward. (I'd have complained a lot less four-five years ago if I had known about this library from the beginning!)
hjh
-
@porres it's mentioned in the valimaki one I posted above: https://www.researchgate.net/publication/260701331_A_Perceptual_Study_on_Velvet_Noise_and_Its_Variants_at_Different_Pulse_Densities
(novel variants on page 7)
edit: it mentions the 'regularity' but not bias.. I can't remember where that came from, maybe that one wasn't in a paper but it's necessary to make it into a pulse train
or it may have come from a different paper on 'extended velvet noise'.. been a few years -
I can't feel any perceptual difference with just positive impulses, for instance....
-
which makes me ask, what would be the purpose of having also negative impulses? what is it for?
-
@porres that's quite a philosophical question.. what are the positive ones for?
edit: as a serious answer, I guess anything that's polarity-specific. you could maybe combine multiple generators in different ways?
I guess you could always multiply by -1 but to me it seems more natural to have it go from 1 to -1 since that's the output range of digital audio and it would take extra objects.. easier just to allow negative values -
@seb-harmonik.ar said:
I do think @manuels original idea of having a sample-increment offset still works without missing periods?
Why don't you think it works with non-integer period lengths?a phasor~ is always guaranteed to have its last sample be within the last sample increment regardless of whether an integer-period or not, and
[wrap~]
will pretty much perfectly wrap the phasor~'s phase..With non-integer period lengths you have effectively a changing number of samples per period. That in itself I don't think would be a problem, but adding a random value and wrapping the result can give you sample-increments that are either smaller or bigger than the calculated value.
Maybe an extreme example can help to clarify: Consider a period length of 2.5 samples. The sample increment is in this case 0.4. If you have a period with the sample values 0.3 and 0.7, add 0.8 as a random value and wrap, what you get is 0.1 and 0.5, so the last sample doesn't get above 1 when you add the calculated sample-increment of 0.4. Am I missing something?
@ben.wes Did you do the testing with non-integer fractions of your sampling frequency? You mentioned 3kHz at 48kHz SR as an example, which shouldn't make problems ....
-
@manuels hmm yeah I guess it doesn't quite work due to the phase discontinuities..
maybe have to do a bit more tinkering with the offset/phase reset part
I wonder if it would work to just discard the wrapped around part somehow, and set the limit based on the 'non-fractional' part of the period -
@manuels said:
@ben.wes Did you do the testing with non-integer fractions of your sampling frequency? You mentioned 3kHz at 48kHz SR as an example, which shouldn't make problems ....
sorry for the confusion! - it weren't exactly 3kHz, since I'm setting the frequency with a logarithmic slider. tested once more with 3026.2Hz here now (which was probably also the value yesterday). i'm displaying the last 3 outlets here that i added to your patch (additionally offsetting the phasor for visual clarity):