Author |
Message |
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Sat Sep 01, 2007 12:19 pm Post subject:
|
|
|
Is it because "^" in that language needs a lot of calculations?
If it's the case, can you try using
in0 * in0 instead of in0 ^ 2
and in0 * in0 * in0 instead of in0 ^ 3?
(and also on another power signs)
If i'm not wrong, using multiplication straight ahead like this could really save a lot of CPU power. |
|
Back to top
|
|
|
Consul
Joined: May 05, 2007 Posts: 59 Location: Port Huron, Michigan, USA
|
Posted: Sat Sep 01, 2007 12:44 pm Post subject:
|
|
|
Yeah, I was thinking the same thing myself. I guess it's worth a try.
EDIT: Oh, yeah! HUGE difference. Both algos are down to 1.7-1.8% now. Time to integrate these into the new Compstortion code (which has log-based input gain and output attenuation in it now). _________________ Darren Landrum
"Never be afraid to try something new. Remember that a lone amateur built the Ark. A large group of professionals built the Titanic." - Dave Barry |
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Sat Sep 01, 2007 3:02 pm Post subject:
|
|
|
Consul: I've got a new formula for you to try:
I've been playing around with these transfer functions:
x/(1+|x|) - - - (1)
x / (1 + x^2) - - - (2)
x^3 / (1 + |x^3|) - - - (3)
and I like their characters..
But there is a problem with the x^3 / (1 + |x^3|)
is that.. if the amplitude of the input signal is very low,
the output would be much lower
The plot of this function already shows what I mean, you can take a look at:
http://electro-music.com/forum/gallery2.php?g2_itemId=6344
Actually, I'm aware of this problem since I tested it,
but I just couldn't wait to spread it because it has such an interesting overdrive characteristic and I like it.
So.. This new one will be .. hmm
sort of.. a combination of (1) and (3) in character
but without the particular problem.
f(x) = x(1+x^2) / (1 + | x(1+x^2) | )
the plot of the function:
http://electro-music.com/forum/gallery2.php?g2_itemId=6346
If we replace x^2 with x^4, we'll get a more "squarish" sound,
or replace with x^2+x^4 to get that character but with smoother sound.
I'll display the implementation in ChucK here soon.
- - -
Here's the test of the above formula's implementation in ChucK
Code: | class overdrive03_01_02
{
// this overdrive UGen applies f(x) = x(1+x^2) / (1 + abs(x(1+x^2))) waveshaping function
// to the "in"put signal and output to "out".
Gain in; Gain out; // chuck or unchuck this to the outside world to connect;
// prepare f(input) = input(1+input^2)
Step one => Gain f1;
1.0 => one.next; <-- 1
in => Gain f2;
in => Gain inDummy1 => f2;
3 => f2.op; <-- input ^ 2
f2 => f1; <-- 1 + input ^ 2
in => Gain f;
f1 => f;
3 => f.op; <-- input(1 + input^2)
one => Gain divisor;
f => FullRect Abs; <-- abs(f)
Abs => divisor; <-- 1 + abs(f)
// calculate f / (1 + abs(f)) and send to "out"
f => out;
divisor => out;
4 => out.op; <-- make out do a division of the inputs
}
// Testing by feeding Sine Wave at 110hz into the drive unit.
overdrive03_01_02 drive;
SinOsc s => drive.in;
drive.out => dac;
110.0 => s.freq;
for(int i; i < 10; i++)
{
i * .5 => s.gain;
second => now;
} |
and this is for the replacement of x^2 to x^4
Code: | class overdrive03_01_03
{
// this overdrive UGen applies f(x) = x(1+x^4) / (1 + abs(x(1+x^4))) waveshaping function
// to the "in"put signal and output to "out".
Gain in; Gain out; // chuck or unchuck this to the outside world to connect;
// prepare f(input) = input(1+input^2)
Step one => Gain f1;
1.0 => one.next; <-- 1
in => Gain f2;
in => Gain inDummy1 => f2;
f2 => Gain f3;
f2 => Gain f2Dummy1 => f3;
3 => f2.op;
3 => f3.op; <-- input ^ 4
f2 => f1; <-- 1 + input ^ 4
in => Gain f;
f1 => f;
3 => f.op; <-- input(1 + input^4)
one => Gain divisor;
f => FullRect Abs; <-- abs(f)
Abs => divisor; <-- 1 + abs(f)
// calculate f / (1 + abs(f)) and send to "out"
f => out;
divisor => out;
4 => out.op; <-- make out do a division of the inputs
}
// Testing by feeding Sine Wave at 110hz into the drive unit.
overdrive03_01_03 drive;
SinOsc s => drive.in;
drive.out => dac;
110.0 => s.freq;
for(int i; i < 10; i++)
{
i * .5 => s.gain;
second => now;
} |
- - -
Hmm the sound's not that different while testing with SinOsc.
I'd better test it with more instruments soon..
Guitars, Rhodes, Organ, Synth, Drums, ETC.
NOTE: These example uses the new ChucK 1.2.1.0 comment feature:
using <-- is like commenting with // now
so if you're on an older ChucK version,
you can put // in front of every <-- I used for commenting. |
|
Back to top
|
|
|
Consul
Joined: May 05, 2007 Posts: 59 Location: Port Huron, Michigan, USA
|
Posted: Sat Sep 01, 2007 3:46 pm Post subject:
|
|
|
I really wish I had your math skills.
I'll play around with this and report back.
EDIT: Well, I'm reporting back, and I can barely hear the difference between this latest algo with x^2 and the bypassed state, to tell you the truth. With the x^4 variation at very high drives, it gives something of a subtle exciter sound more than anything, which is not bad in and of itself, really. I'm going to play around with that some more, and maybe make it it's own plugin.
In the end, I think I'll stick with the first two algos, and play around with this latest one later.
Now I get to figure out how to do a filter. I don't know if I'm up to it.
EDIT 2: The Jesusonic version of these algorithms are horribly program-dependent, to the point that it's frustrating me. I don't know what to do about that, other than let people decide what they want to do with it, if anything. _________________ Darren Landrum
"Never be afraid to try something new. Remember that a lone amateur built the Ark. A large group of professionals built the Titanic." - Dave Barry |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Tue Dec 18, 2007 3:46 am Post subject:
|
|
|
Related to this topic I have a feature request for a WaveShaper class.
It would take a chucked input and output a shaped wave:
ouput = WaveShaper.function(input);
Different functions would at least include:
-Polynomial with user defined coefficients (up to 8th degree would propably be enough).
-Trigonometric (sin,cos,tan,asin,acos,atan)
-Exponential
-Logarithmic (natural)
-Hyperbolic (sinh,cosh,tanh,asinh,acosh,atanh) //These could be done with exp, ln and .op(4) but it's nice to have them predifined.
-Limit: if(input > upper_limit) output = upper_limit;
if(input < lower_limit) output = lower_limit;
else output = input; |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Sat Feb 02, 2008 8:44 am Post subject:
|
|
|
Here's my take on a distortion class:
Code: | class Distort{
Gain in => Gain overdrive;
Gain out;
Step unity; 1.0 => unity.next;
Event process;
fun UGen chuck(UGen @ u){
u => in;
return out;
}
fun void stop(){
process.broadcast();
}
fun void order1(){ // y = x / (abs(x)+1)
overdrive => Gain div => out;
4 => div.op;
unity => Gain sum => div;
overdrive => FullRect abs => sum;
process => now;
div =< out;
}
fun void order2(){ // y = (x*abs(x)+ x) / (x*x+abs(x)+1)
overdrive => Gain nominator_sum => Gain div => out;
4 => div.op;
unity => Gain denom_sum => div;
overdrive => FullRect abs => denom_sum;
overdrive => Gain abspow2 => nominator_sum;
3 => abspow2.op;
abs => abspow2;
abspow2 => FullRect pow2 => denom_sum;
process => now;
div =< out;
}
fun void ribbon(){ // y = x / (0.25*x*x + 1)
overdrive => Gain div => out;
4 => div.op;
unity => Gain sum => div;
overdrive => Gain pow2 => sum;
3 => pow2.op;
overdrive => Gain pow2dummy => pow2;
0.25 => pow2.gain;
process => now;
div =< out;
}
fun void remove_linear(){
in =< overdrive;
process => now;
in => overdrive;
}
fun void overdrive3(){ //Thanks to kijjaz for the idea
in => Gain pow3 => overdrive;
3 => pow3.op;
in => Gain pow3dummy1 => pow3;
in => Gain pow3dummy2 => pow3;
process => now;
pow3 =< overdrive;
}
fun void overdrive5(){
in => Gain pow5 => overdrive;
3 => pow5.op;
in => Gain pow2 => pow5;
3 => pow2.op;
in => Gain pow2dummy => pow2 => Gain pow4dummy => pow5;
process => now;
pow5 =< overdrive;
}
}
Distort d;
SinOsc s => d.chuck => dac; //Can be chucked almost like a real UGen :)
220.0 => s.freq;
//Play 3 second crescendos with the SinOsc
//Try order1
spork~d.order1();
0.0 => s.gain;
for(now + 3::second => time later;now < later; 10::ms => now){
s.gain() + 0.01 => s.gain;
}
d.stop();
second => now;
//Try order2
spork~d.order2();
0.0 => s.gain;
for(now + 3::second => time later;now < later; 10::ms => now){
s.gain() + 0.01 => s.gain;
}
d.stop();
second => now;
//Try some heavy overdrive with ribbon
spork~d.remove_linear();
spork~d.overdrive3();
spork~d.overdrive5();
spork~d.ribbon();
0.0 => s.gain;
for(now + 3::second => time later;now < later; 10::ms => now){
s.gain() + 0.01 => s.gain;
}
d.stop();
second => now;
d.out =< dac; //d.out is silent but let's unchuck for good measure
s =< d.in; //This is actually not necessary because after calling d.stop() d.in isn't connected to anything.
1.0 => s.gain;
s => dac; //Just a final unprocessed beep
second => now;
|
EDIT: I just tried this one in action in a song... It generates heavy garbage when called and sporked multiple times... you have been warned.
(Or my laptop is acting up again)
EDIT2: I fixed a bug with overdrive5 and added y = x/(0.25*x*x + 1) _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
meestaplu
Joined: Apr 22, 2008 Posts: 1 Location: Connecticut
|
Posted: Tue Apr 22, 2008 7:35 pm Post subject:
|
|
|
I implemented a lookup table in ChucK that lets you do a tanh distortion in less than 10 lines:
Code: | int i;
float v;
2048 => int MAX;
1.03 => float nor;
for(-MAX => i; i<MAX; 1 +=> i) {
Math.tanh(7*(i+0.0)/MAX)/nor => v;
//(i+0.0)/MAX => float x;
//Math.sin(x*pi/2.0)*0.99 => v;
lut.set(i+MAX, v);
}
SinOsc sin_osc => lut => dac;
|
I left a sine distortion in there, commented out, so you can see how to use different values.
It's kind of crappy right now, but it works.
It's a unit generator called LUT (lookup table) that has 4096 buckets. Bucket 0 maps input value -1.0 to an output value...bucket 4095 maps input value 1.0 to an output value.
The idea is that you precompute your transfer function -- because of the precomputation it doesn't take much CPU to do real-time processing. When I get it decent, I'll submit it as a patch to the official build so others can use it -- I don't like my .set() function, though, and would rather have an array input so you don't have to keep in mind the secret number of buckets in the LUT.
What do you think on the interface?
Matt
[edit: disabled HTML] |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Wed Apr 23, 2008 12:11 am Post subject:
|
|
|
A nice idea.
I'd really like to use chucks own float arrays as the lookup table and then just @=> it to the LookUpTable UGen.
Well actually I'm thinking about implementing DigitalTape,an interpolating lookup (and writeup :) ) table with fractional loop point control using chuck's float array as the samples.
But a CPU effecient UGen like you have in mind would come in handy too.
Btw. Where are you planning on posting the source once you're done? _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Wed Apr 23, 2008 12:29 am Post subject:
|
|
|
oh yeah.. that'd be great. if we can have lookup table ugen that can easily be used with a float array,
we'll have a lot more implementations. |
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Thu Jul 03, 2008 1:03 pm Post subject:
|
|
|
Today I was chatting with avaruus (in #chuck in freenode irc) and we talked about distortion, so I came back to this topic.
After looking around seeing some general overdrive I prepared as classes in here,
I came up with the idea of joining some ideas in one new class.
here is the result:
overdrive transfer function:
f(x) = f(x) = (ax + bx^2 + cx^3) / (1 + |ax| + bx^2 + |cx^3|)
with initial value a = 1, b = 1, c = 1
here's the easy-to-use result:
Code: | class kjzGenOverdrive01
{
// this class calculate overdrive transfer function from this function:
// f(x) = (ax + bx^2 + cx^3) / (1 + bx^2 + |ax + cx^3|)
// to set a, b, c
// use aInit.next, bInit.next, cInit.next
// or if you want to adjust a, b, c by multiplying with other signal,
// chuck the signals to ax, bxx, cxxx (their .op's are all MULTIPLY in here)
Gain input, output; // chuck or unchuck this to connect
Step aInit; aInit.next(1); // initialize a
Step bInit; bInit.next(1); // initialize b
Step cInit; cInit.next(1); // initialize c
aInit => Gain ax; input => ax; ax.op(3); // calculate ax
bInit => Gain bxx; input => bxx; input => Gain dummyB1 => bxx; bxx.op(3); // calculate bx^2
cInit => Gain cxxx; input => cxxx; input => Gain dummyC1 => cxxx; input => Gain dummyC2 => cxxx;
cxxx.op(3); // calculate cx^3
Gain UPPER; // prepare the upper part of the division
ax => UPPER; bxx => UPPER; cxxx => UPPER; // calculate ax + bx^2 + cx^3
Step one; // prepare 1
ax => Gain axANDcxxx; cxxx => axANDcxxx; // calculate ax + cx^3
axANDcxxx => FullRect ABSaxANDcxxx; // calculate |ax + cx^3|
Gain LOWER; // prepare the lower part of the division
one => LOWER; bxx => LOWER; ABSaxANDcxxx => LOWER; // calculate 1 + bx^2 + |ax + cx^3|
UPPER => output;
LOWER => output;
output.op(4); // calculate f(x) by dividing UPPER with LOWER
} |
and this.. the test code:
Code: | kjzGenOverdrive01 OD;
// change these to hear different drive characters
OD.aInit.next(2);
OD.bInit.next(3);
OD.cInit.next(5);
// - -
SinOsc s => OD.input;
OD.output => dac;
for(int i; i < 10; i++)
{
(i + 1) => s.gain;
second => now;
} |
please feel free to test (over)drive.
- - - - -
There is also another thing, the easy clipper I posted quite some time ago on the wiki, you can check out also at http://wiki.cs.princeton.edu/forums.html/ChucK/kijjaz-utility-classes.ck
Code: | class kjzClipper01 // clip signal within -1 to 1 with simple UGens
{
Gain input; // chuck input signal to this
Gain output; // chuck this out to have the result
Step one; 1 => one.next;
input => HalfRect a;
one => a; // calculate a from HalfRect(input + 1)
one => Gain two; 2 => two.gain;
-1 => a.gain;
a => HalfRect b;
two => b; // calculate b from HalfRect(2 - HalfRect(input + 1))
-1 => b.gain;
one => output;
b => output; // the result we want: 1 - HalfRect(2 - HalfRect(input + 1))
} |
|
|
Back to top
|
|
|
kijjaz
Joined: Sep 20, 2004 Posts: 765 Location: bangkok, thailand
Audio files: 4
|
Posted: Sun Jul 06, 2008 8:17 pm Post subject:
|
|
|
This is the same version,
but the coefficients (a, b, c) can be adjusted for both upper and lower part of the division.
with this, the overdrive can be more dangerous to control,
but can craft a more variety of tones,
for example, using negative coefficients.
Code: | class kjzGenOverdrive01deep
{
// this class calculate overdrive transfer function from this function:
// f(x) = (a1x + b1x^2 + c1x^3) / (1 + |a2x| + b2x^2 + |c2x^3|)
// to set a, b, c
// use a1Init.next, b1Init.next, c1Init.next
// and a1Init.next, b1Init.next, c1Init.next
// or if you want to adjust a, b, c by multiplying with other signal,
// chuck the signals to ax, bxx, cxxx (their .op's are all MULTIPLY in here)
Gain input, output; // chuck or unchuck this to connect
Step a1Init; a1Init.next(1); // initialize a1
Step b1Init; b1Init.next(1); // initialize b1
Step c1Init; c1Init.next(1); // initialize c1
Step a2Init; a2Init.next(1); // initialize a2
Step b2Init; b2Init.next(1); // initialize b2
Step c2Init; c2Init.next(1); // initialize c2
a1Init => Gain a1x; input => a1x; a1x.op(3); // calculate a1x
b1Init => Gain b1xx; input => b1xx; input => Gain dummyB1 => b1xx; b1xx.op(3); // calculate b1x^2
c1Init => Gain c1xxx; input => c1xxx; input => Gain dummyC1 => c1xxx; input => Gain dummyC2 => c1xxx;
c1xxx.op(3); // calculate c1x^3
Gain UPPER; // prepare the upper part of the division
a1x => UPPER; b1xx => UPPER; c1xxx => UPPER; // calculate a1x + b1x^2 + c1x^3
Step one; // prepare 1
a2Init => Gain a2x; input => a2x; a2x.op(3); // calculate a2x
b2Init => Gain b2xx; input => b2xx; input => Gain dummyB1_2 => b2xx; b2xx.op(3); // calculate b2x^2
c2Init => Gain c2xxx; input => c2xxx; input => Gain dummyC1_2 => c2xxx; input => Gain dummyC2_2 => c2xxx;
c2xxx.op(3); // calculate c2x^3
a2x => Gain a2xANDc2xxx; c2xxx => a2xANDc2xxx; // calculate a2x + c2x^3
a2xANDc2xxx => FullRect ABSa2xANDc2xxx; // calculate |a2x + c2x^3|
Gain LOWER; // prepare the lower part of the division
one => LOWER; b2xx => LOWER; ABSa2xANDc2xxx => LOWER; // calculate 1 + b2x^2 + |a2x + c2x^3|
UPPER => output;
LOWER => output;
output.op(4); // calculate f(x) by dividing UPPER with LOWER
} |
Test code:
Code: | kjzGenOverdrive01deep OD;
// change these to hear different drive characters
OD.a1Init.next(1);
OD.b1Init.next(0);
OD.c1Init.next(0);
OD.a2Init.next(0);
OD.b2Init.next(-1);
OD.c2Init.next(1);
// - -
SinOsc s => OD.input;
OD.output => dac;
for(int i; i < 10; i++)
{
(i + 1) => s.gain;
second => now;
} |
|
|
Back to top
|
|
|
Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 267
|
Posted: Mon Jul 21, 2008 1:05 am Post subject:
|
|
|
Folks, I'm working with the following distortion class for my Guitar Motion Sensor (GMS) project, and I have some questions.
Code: | // distortion class
class distortion {
// variables
int my_stage; // identifies the stage of this reverb
float my_extremeness; // the extremeness of this reverb
float my_control; // the control value of this reverb
// the patch
Gain input => Gain boost => Gain divide => Gain output;
input => FullRect fwr => Gain add => divide;
Step step => add;
// the patch parameters
1.5 => boost.gain;
4 => divide.op; // make it a divider
1.0 => step.next;
// potentiometer adjust function
fun void potentiometer_adjust () {
while (true) {
potentiometer => now;
extremeness[my_stage] => my_extremeness;
my_extremeness * my_control => input.gain;
}
}
// accelerometer adjust function
fun void accelerometer_adjust () {
while (true) {
accelerometer => now;
control[my_stage] => my_control;
my_extremeness * my_control => input.gain;
}
}
}
|
I guess the main question is how would you control it. The software provides two input controls, both ranging from 0 to 1 as floats. They are "extremeness" and "accelerometer", where extremeness is set by user control to a fixed value during configuration, and accelerometer is the dynamic input from the system. How would you use these controls to shape distortion? Isn't there a tau parameter that shapes the curve? _________________ "Let's make noise for peace." - Kijjaz |
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
|
Back to top
|
|
|
Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 267
|
|
Back to top
|
|
|
Frostburn
Joined: Dec 12, 2007 Posts: 255 Location: Finland
Audio files: 9
|
Posted: Mon Jul 21, 2008 5:37 am Post subject:
|
|
|
Inventor wrote: | tau*x/(1+tau*|x|) |
For tau < 1.0 I wouldn't put it before the expression. It limits the dynamic range too much. So here's my suggestion:
x , tau = 0
x/(1+tau*|x|) , tau <= 1
tau*x/(1+tau*|x|) , tau greater than 1
So that's basically:
max(tau,1)*x/(1+tau*|x|)
Chuck doesn't have the max function but you can make one from the HalfRect UGen.
max(tau,1) := 1 - halfrect(1 - tau) _________________ To boldly go where no man has bothered to go before. |
|
Back to top
|
|
|
Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 267
|
Posted: Mon Jul 21, 2008 6:42 am Post subject:
|
|
|
OK, I can do that. Now, is doing that essentially the same as scaling the input by a variable amount? I know, lotsa questions but I want to get this right. Also, on tremolo, I have the following function:
Code: | // tremolo class
class tremolo {
// parameters
4.0 => float frequency_depth; // how deep to vary frequency
// variables
int my_stage; // identifies the stage of this reverb
float my_extremeness; // the extremeness of this reverb
float my_control; // the control value of this reverb
// the patch
Gain input => Gain multiply => Gain output;
SinOsc sinosc => Gain sum => multiply;
Step step => sum;
// the patch parameters
3 => multiply.op; // make it multiply
1.0 => step.next; // sine wave offset
// potentiometer adjust function
fun void potentiometer_adjust () {
while (true) {
potentiometer => now;
extremeness[my_stage] => my_extremeness;
my_extremeness * frequency_depth => sinosc.freq;
}
}
// accelerometer adjust function
fun void accelerometer_adjust () {
while (true) {
accelerometer => now;
control[my_stage] => my_control;
my_control => sinosc.gain;
my_control => step.next;
}
}
}
|
I don't know, is that frequency_depth value of 4.0 too small? Is the tremolo waveform (1+sin(x)) too subtle for rock? Should it be halfrect(sin(x)) for more zero-time? _________________ "Let's make noise for peace." - Kijjaz |
|
Back to top
|
|
|
rogan
Joined: Dec 16, 2007 Posts: 83 Location: Urbana, IL
Audio files: 5
|
Posted: Wed Sep 24, 2008 11:31 pm Post subject:
|
|
|
Foolin around with some real simple distortion, but I thought I'd share.
Wobble wobble:
Code: |
// Sounds so good with Sqr Tri and Sin !!
SinOsc signal => Gain one;
signal => Gain two;
.75 => one.gain;
1.0 - one.gain() => two.gain;
one => SqrOsc overdrive => LPF lpf => dac;
two => TriOsc od2 => lpf => dac;
1 => overdrive.sync; // set sync option to Phase Mod.
1 => od2.sync;
1 => signal.gain;
48 =>signal.freq;
SinOsc roller => blackhole;
2 => roller.sync;
10 => roller.gain;
3.147 => roller.freq;
signal => roller;
72 => lpf.freq;
while (true) {
lpf.freq() + roller.last() => lpf.freq;
4::ms => now;
if (Std.rand2f(0.,1.) < .005) {
change() => signal.freq;
}
}
fun float change () {
Std.rand2f(0.,1.) => float rand;
if ( rand < 0.4 ) {
return 48.0;
} else if ( rand < 0.8 ) {
return 37.0;
} else {
return 33.0;
}
}
|
|
|
Back to top
|
|
|
Inventor
Stream Operator
Joined: Oct 13, 2007 Posts: 6221 Location: near Austin, Tx, USA
Audio files: 267
|
Posted: Fri Sep 26, 2008 11:11 am Post subject:
|
|
|
Just a little observation on how to control the intensity of the distortion: vary the constant like this:
Code: | input / (k + Math.abs(input) ) => output |
When you set k to 1 you get a little distortion, and when you set it to 0.1 you get a lot.
At first I tried leaving the value of k=1 and multiplying the input by some value to increase distortion, but i got tons of noise because I was obviously amplifying the noise. duh.
So eventually, and it's comical how long it took me to figure this out but i'm busy with 1,000 things, i figured out that mathematically speaking, multiplying the input by alpha is the same as dividing the constant k by alpha. no duh.
Think about it at the extreme case of alpha = infinity, then k = 0 and the output is simply the sign of the input, which is the sharpest distortion possible.
That may seem really obvious in hindsight but it wasn't obvious to me at first glance, so there you go. Another one ChucKs the dust. _________________ "Let's make noise for peace." - Kijjaz |
|
Back to top
|
|
|
cbit
Joined: Dec 01, 2005 Posts: 35
|
Posted: Sun Nov 15, 2009 11:06 am Post subject:
|
|
|
kijjaz wrote: |
Hmm.. How can I test the exact consumption rate of CPU that
chuck is consuming? hopefully for comparing between shreds?
I'd like to try that sometimes to compare between various methods. ^_^ |
Did you find a way? I'm interested in this too. Thanks for the nice overdrive class! _________________ http://basementhum.blogspot.com |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Mon Nov 16, 2009 11:49 am Post subject:
|
|
|
On Linux or OSX; open a shell and type "top", that should give you cpu usage for ChucK and other programs on your system. On Windows the activity monitor should display this (hit ctrl+alt+delete to bring it up) _________________ Kassen |
|
Back to top
|
|
|
kurtk
Joined: Jan 27, 2010 Posts: 8 Location: usa
|
Posted: Fri Apr 30, 2010 5:56 am Post subject:
|
|
|
Hey all,
I was reading through this thread about distortion algorithms and there are some really good ones here. The problem is that in ChucK we have to do math every sample to implement them. I think ChucK needs 'Table' UGen that can hold arbitrary function tables. It would need an accessor to the raw values inside of it so it could be filled like a normal ChucK array. Maybe a size constructor. And maybe some methods to set the mode of indexing/reading from the table when a UGen is connected (i.e. [0, 1] or [-1, 1]. And of course interpolation.
Like this...
Code: |
Phasor phs => Table t => dac;
1024 => t.size;
for (0 => int i; i < t.size(); i++) {
Math.sin((i $ float/t.size())*2*pi) => t[i];
}
day => now;
|
Just something I have always been missing in ChucK.
(now we just need separate delay read and write objects...)
Later.
Kurt _________________ .............................................
http://kurtkotheimer.com
............................................. |
|
Back to top
|
|
|
heuermh
Joined: Dec 15, 2006 Posts: 19 Location: minneapolis
|
Posted: Thu Nov 15, 2012 10:52 am Post subject:
|
|
|
I have implemented a WaveShaper Chugen and several subclasses that use the various functions discussed here in LiCK.
Example here
https://github.com/heuermh/lick/blob/master/examples/distExample.ck
Thanks to everyone on this forum topic for inspiration. I've linked to here in the source; if you would prefer I use different class names or otherwise change the attribution, please let me know. |
|
Back to top
|
|
|
|