Mix fill , filter frequency spread

Why is my example not duplicating and spreading the filter frequency ?
The second examle ( from a tutoriall ) does the same thig but rather on pitch frequency + panning , which I have ommited in my example
//
(
{
var a;
a=Saw.ar(220);
Mix.fill(4,{RLPF.ar(a,1000.200.rand,mul:1/4)});
}.play
)
//

///
{ Pan2.ar( Mix.fill( 8, { LFSaw.ar(200 + 200.0.rand, 0, 1 / 8) }), SinOsc.kr( 0.5 ) )  }.play;
//

you’ve got parallel low pass filters. You’re going to get the sound of the highest cutoff + a lumpy eq

also heads up -> 1000.200.rand is giving you a random float between 0 and 1000.2

you want rrand(200,1000)

1 Like

Yes ,the period was a syntax error
I still haven’t succefully achieved what you’re suggesting
I want the filter frequencies to be spread , just like the pitch example ( see above )
Also , why .rrand instead of .rand , the pitch example uses the latter

(
{
var a;
a=Saw.ar(220);
	Mix.fill(4,{RLPF.ar(a,(200+1000.rand),mul:1/4)});
}.play
)

Here side by side , only difference is the filter versus pitch fill, it has the same settings as the pitch example (except higher values ) , but it doesn’t give a filter unsion effect

(
{
 var a;
 a=Saw.ar(220);
	 Pan2.ar(Mix.fill(4,{RLPF.ar(a,(200+1000.rand),mul:1/4)}, SinOsc.kr( 0.5 ) )  );
}.play
)
///
{ Pan2.ar( Mix.fill( 8, { LFSaw.ar(200 + 200.0.rand, 0, 1 / 8) }), SinOsc.kr( 0.5 ) )  }.play;
///

you have a single oscillator going through 4 parrallel low pass filters think about it for a second - a 220 cycle saw wave have a fundamental of 220, a first partial of 440 a second partial at 660 etc.

if you have a low pass filter at 400 and a low pass filter at 500 what you will hear is simply a steeper cutoff above that first partial at 440. You will not get a clear impression of 2 different cutoff points.

now add another one at 1200. Now you have a little more of the first 3 partials and a shallower cutoff above that. again you will not hear distinct filter cutoff levels.

maybe what you want is resonant band pass filters in series!

regarding rrand… not to be a pedant but look it up in the help!

True to that about the lowpass filter, let’s try bandpass filter , we should have resonant peaks for each frequency ( fill is 4 , so four frequencies )
Still no frequency spread
I have looked up about rrand , the reasn why I used .rand is becasue of the example that used it succesfully for the pitch spread .
The manual does not clarify anything on how to achieve filter frequency spread , let alone the use of .rrand
Can you explain why .rand does not work with the filter but does with the pitch example ?
I am at the point of giving up completely .

(
{
 var a;
 a=Saw.ar(220);
	 Pan2.ar(Mix.fill(4,{BPF.ar(a,(200+1000.rand),0.1,mul:1/4)}, SinOsc.kr( 0.5 ) )  );
}.play
)

And as you suggested , still no dice

 (
{
 var a;
 a=Saw.ar(220);
	Pan2.ar(Mix.fill(16,{BPF.ar(a,rrand(200,1000),0.1,mul:1/4)}, SinOsc.kr( 0.5 ) )  );
}.play
)

try Bmoog with a high q (maybe 7) -to hear the peaks it does work it just might not be sounding like you expect!

also higher filters might give more descrimination

Perhaps the fact that the saw waves are identical is part of the problem? not sure what you are hoping to hear

rrand is just a convenient shortcut rather than writing 200+1000.rand you can write rrand(200,1000)

Ok whoa whoa whoa, slow down. No need for that.

As in the other thread, part of the problem here is to define your terms clearly.

“Can you explain why .rand does not work with the filter but does with the pitch example?” So right here – those words “does not work.” They are essentially useless for troubleshooting.

99 times out of a hundred, in programming, “does not work” really means “I expected x but got y.” You’re hearing something different from what you expected. Ok.

So… what is the thing you expected to hear?

Then, problem-solving in programming (at least for me) proceeds like a kind of pincer movement: bottom up (building a lower level component I know I will need), and top down (sketching out the big picture and filling in details one by one with lower level functions). Trying to build the whole thing in one go almost always fails. What works: taking one piece of the puzzle at a time.

I’d suggest: first, make one filter sound the way you want it to. Just one, at one frequency. “Frequency spread” is a separate problem. You don’t have to do frequency spread in your first draft. Just get one filter to sound like you want. You can add the random frequencies later.

Some concrete advice about BPF:

  • If it’s too quiet, try rq = (something); BPF.ar(sig, ffreq, rq) / rq. That changes it to a “constant skirt gain” filter which compensates for the loss of energy.
  • Try different sources. If Saw isn’t getting what you want, try other waves (maybe Blip – sawtooth loses energy in higher partials, Blip doesn’t) or noise. (Noise → BPF is a common formula.)
  • If the fundamental frequency of the input oscillator is higher than the filter frequency, likely that’s wasting a filter. Doesn’t make sense to have a filter preserving frequencies that you already know are not present in the input.
  • Edit: Forgot this one. Filter resonance, the sense of pitch may be a bit weak – but distort the f@*! out of it, and the pitch becomes stronger (as in Underworld’s “Rez”).

One step at a time.

hjh

2 Likes

PS the BPFs already do have “frequency spread”:

(
a = {
 var a;
 a=Saw.ar(220);
	 Pan2.ar(Mix.fill(4,{BPF.ar(a,(200+1000.rand),0.1,mul:1/4)}, SinOsc.kr( 0.5 ) )  );
}.play
)

a.trace;

a.free;

Scanning the trace output for BPF lines:

  unit 1 BPF
    in  0.196408 1056 0.1
    out 0.0355624

  unit 3 BPF
    in  0.196408 890 0.1
    out 0.0887948

  unit 5 BPF
    in  0.196408 829 0.1
    out 0.0286774

  unit 7 BPF
    in  0.196408 680 0.1
    out -0.0250518

So you have 4 BPFs with frequencies 1056, 890, 829, 680.

“Can you explain why .rand does not work with the filter but does with the pitch example ?” – it is already working with the filter.

The problem is with the sound-generation approach.

hjh

Sorry but the statement that the saws are the same frequency doesn’t matter att all ,
Here’s a simple example I did in reaktor which I know like the back of my hand
Altough you only see one osc module and 1 filter module , there are in fact 4 of each becausee the ensemble is set to four voices .
I used the voice count to divide the frequency of the filter : 8000 by 4 (nr. of voices ) and then multiplied by each voice ( which has a unique i.d. number starting from 1,2,3 etc) , so you get resonant peaks at 2000,4000,6000,anfd 8000 hz , whcih you clearly see in the spectrum view
The saw oscillator set to midi pitch 32 , and this goes for all 4 duplicates ( some slight detuning of 50 cents per osc.) ,

This is what I wanted to achieve in supercollider , more or less with random filter frequency deviation

(
a = {
	var sig = Saw.ar(32.midicps);
	// or [2000, 4000, 6000, 8000] or Array.series(4, 2000, 2000)
	var freqs = (2000, 4000 .. 8000);
	var rq = MouseY.kr(1, 0.01, 1);
	var filters = BPF.ar(sig, freqs, rq) / rq;
	(filters.sum * 0.1) ! 2
}.play;
)

a.free;

With the mouse up toward the top (Q approaching 100):

So you used a different oscillator frequency and different filter frequencies from your Reaktor patch… I’m not quite surprised that it didn’t sound the same.

Acoustical reason: If the oscillator is at 220 Hz, partials will be 220, 440, 660, 880, 1100, 1320 and so on. The randomly chosen filter frequencies are between 200 and 1200 Hz – so the harmonics available to be filtered are very widely spaced compared to the filter frequencies. There’s no way you’ll get clearly defined resonant peaks that way – raising the oscillator by a factor of 4 and dropping the filters by a factor of 10 totally changes the behavior of the system. The result you reported initially is acoustically correct for the parameters given.

hjh

Note that you are using resonant band bass filters in reaktor. Have you tried that?

Also when you write “sorry but your statement… doesnt matter at all” this reads as angry. Bear in mind that we are just fellow users here…

I am certainly having difficulties explaining myself , thanks for the upload but that’s not what I wanted
, but is that just one filter with four frequencies ( written in the array ) ,
The reaktor example was just a showcase of filter spread .

Either way , both of you thanks for the help @semiquaver by no means was my comment meant to be agressive .
I hope you can understand that this is a bit frustrating for me , at least the whole coding concept .
Sometimes I wonder why I am learning supercollider since I can do this stuff in reaktor withouut to much haslee ( reaktor core has it’s flaws too ) but there is something satisfying and magical about writing a few lines of code .

edit
At least I learned something new , writing (100,200…600) gives an array with increments of 100 up to 600 ( edit wrong about that one)
But I think you wrote an error in your comment line or Array.series(4, 2000, 2000) (this gives nothing )
Shouldn’t that be [4,2000,2000] ?
This is incredibly powerfull , by just typing an array in filter frequency , we’re essentially making duplicates of that filter , + sum
Can you understand why it is so frustrating , sum + array are essential for this , yet no combination of these kind of examples are to be found.
Sure the manula talks about adressing the left and right output etc… but not how the sum can be used etc…

Question how would one write , without the komma being interpreted as the start of new argument
I know I could assign this to a variable , but still
Start from freq 100 , increments by 50hz up to 400

(
{
SinOsc.ar(100,50…400)],mul:1/8).sum
}.play
)

this works

(
{  
	var pop,sig;
	pop=[100,200,300,400,500,600];
	sig=SinOsc.ar(pop,mul:1/8);
	sig.sum
}.play
)

this does not
(
{
var pop,sig;
pop=(100,200…600);
sig=SinOsc.ar(pop,mul:1/8);
sig.sum
}.play
)

Hm now it does …weird
Edit I was wrong in thinking that ( 100,50…600) meant increment by 50 from 100 to 600

two dots, not 3:
(100,200…600);

There is no such thing as “one” BPF with four frequencies.

In fact, what I wrote does evaluate to four BPFs.

Go ahead, run the synth and then a.trace it. Count the number of BPFs.

This is explained in the Multichannel Expansion help file.

A comment line gives nothing.

If you select only the Array.series expression, it gives you the array.

I literally just wrote you an example of this!

hjh

I know that a comment line gives nothing ( I see that as an insult ) :slight_smile:
YOu wrote in comment as an alternative method Array series (4, 2000, 2000)
When pasted and exectuted ( not as a comment :slight_smile: it does not give an array
Only later I found out that ‘Array series’ is part of code
Array.series(4, 2000, 2000)

And I sincerely thank you for the.sum example , just trying to say that this would be welcome in the manual .
Supercollider is almost impossible to learn with just the manual

I honestly didn’t intend any insult – I had written a correct expression and was surprised to hear that it produced nothing, and I was speculating as to reasons why a correct expression would produce nothing. Accidentally running it as a comment is a plausible reason… I’m sorry my remark was taken badly.

With that said, we’re in a context here where people are trying to help you and you’ve been quite argumentative. I also feel insulted by some of the exchange here.

If you don’t understand code that someone has posted, I’d like to suggest that maybe it would be a better approach to ask why the example is written that way, instead of “thanks for the upload but that’s not what I wanted” (it is what you wanted! – basically implying that I don’t understand a parallel filter bank or how to write it). That was frustrating… taking time to explain something and being told “you don’t get it”… not a good way to treat volunteer helpers.

I agree with you here.

Programmers are often bad at technical writing.

SC documentation tends to focus on objects and methods and largely excludes patterns of usage. I’ve been making that comment for years but time is scarce, for all of us. Some years ago I wrote documentation for patterns that includes a “Cookbook” section of common use cases. We could use a synthesis cookbook but it hasn’t been written yet.

hjh

Ah, and I forgot about this one.

You found a solution using a variable – that’s good, and it works, but you have asked how to do it without a variable.

Let’s use code formatting to answer that question:

(
{
	SinOsc.ar(
		something about frequencies,
		mul: 1/8
	)
}.play;
)

So then what is the “something about frequencies”?

Start from freq 100 , increments by 50hz up to 400

… which you had wanted to write using series notation: (100, 150 .. 400).

So then it’s:

(
{
	SinOsc.ar(
		(100, 150 .. 400),
		mul: 1/8
	)
}.play;
)

And you can collapse that onto one line:

(
{
	SinOsc.ar((100, 150 .. 400), mul: 1/8)
}.play;
)

Does that look weird, with the doubled parentheses? It kinda does… which is probably why you didn’t think of it. But the two pairs of parentheses have different meanings. The outer pair encloses the argument list for ar. The inner pair is for the series notation.

Because this situation needs series notation inside an argument list, you have to have both pairs.

As a general comment: Based on reading a lot of your posts, I get the impression that, in code, you’re reading the words and numbers as very important and the symbols as not so important. (For instance, when I wrote Array.series(...) = “Array -dot- series(…)” and you read “Array series,” or my series notation had two dots and you read three.)

The symbols are just as important as the words. It’s a matter of retraining your eye to catch these details.

hjh

Valuable information as always
Cheers , this forum is a huge help