Difference between revisions of "Example 3"
(→SuperCollider code) |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 40: | Line 40: | ||
SinOsc m => SinOsc c => dac; | SinOsc m => SinOsc c => dac; | ||
− | + | 2 => c.sync; //sync mode 2 tells SinOsc to interpret input as offset to the internal frequency cf | |
− | 550 => m.freq; | + | |
+ | 550 => float mf => m.freq; | ||
+ | 300 => float cf => c.freq; | ||
2 => float index; | 2 => float index; | ||
− | + | index * mf => m.gain; | |
− | |||
− | |||
while( true ) 1::second => now; | while( true ) 1::second => now; | ||
− | and, | + | and, if you are interested, the new ChubGraph feature in ChucK allows you to define new composite UGENS, which is handy here: |
+ | |||
+ | <pre> | ||
+ | class MyFM extends Chubgraph | ||
+ | { | ||
+ | SinOsc m => SinOsc c => outlet; | ||
+ | |||
+ | 2 => c.sync; //sync mode 2 tells SinOsc to interpret input as offset to the internal frequency cf | ||
+ | |||
+ | //set some default values | ||
+ | 550 => float mf => m.freq; | ||
+ | 300 => float cf => c.freq; | ||
+ | 2 => float index; | ||
+ | index * mf => m.gain; | ||
+ | |||
+ | fun float set_cf(float f) | ||
+ | { | ||
+ | f => cf => c.freq; | ||
+ | return cf; | ||
+ | } | ||
+ | |||
+ | fun float set_mf(float f) | ||
+ | { | ||
+ | f => mf => m.freq; | ||
+ | index * mf => m.gain; | ||
+ | return mf; | ||
+ | } | ||
+ | |||
+ | fun float set_index(float f) | ||
+ | { | ||
+ | f => index; | ||
+ | index * mf => m.gain; | ||
+ | } | ||
+ | |||
+ | fun void set_all(float newcf, float newmf, float newindex) | ||
+ | { | ||
+ | newcf => cf => c.freq; | ||
+ | newmf => mf => m.freq; | ||
+ | newindex => index; | ||
+ | index * mf => m.gain; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | MyFM testfm => dac; | ||
+ | 1::second => now; | ||
+ | |||
+ | testfm.set_all(400, 250, 2.5); | ||
+ | 1::second => now; | ||
− | + | //and now, add a 2nd, in parallel | |
− | + | ||
− | + | MyFM testfm2 => dac; | |
− | + | 1::second => now; | |
− | + | </pre> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Latest revision as of 11:20, 15 January 2013
FM synthesis:
ChucK code
SinOsc c => Gain amp => dac; // carrier SinOsc m => blackhole; // modulator 0.3 => amp.gain; 550 => float mf => m.freq; 300 => float cf => c.freq; 2 => float index; while( true ) { cf + (index * mf * m.last()) => c.freq; 1::samp => now; }
SuperCollider code
{ var cf, mf, index; cf = 300; mf = 550; index = 2; SinOsc.ar(cf + SinOsc.ar(mf, mul: mf * index), mul: 0.3).dup // .dup = duplicate = cheap stereo }.play;
SC actually has a PM UGen (Phase Modulation synthesis and Frequency Modulation synthesis are basically the same sound), so this example could also look like this:
{PMOsc.ar(300,550,2,mul:0.3).dup}.play;
from DT here: this is super cool Jascha! there is also a ChucK FM synthesis ugen:
http://chuck.cs.princeton.edu/doc/program/ugen_full.html#FM
from JN: neat-o - this should totally be added to the ChucK code section as an alternative approach. i couldn't immediately see how to use it - can you post an example?
from DT: well, FM by itself doesn't actually work, which is silly (it's meant to be a superclass only), but ChucK is full of silliness. however, FM synthesis is possible very simply and efficiently using the .sync method, which many UGENS have, and which tells the UGEN how to interpret its input. so, here's a very simple example, from the ChucK examples:
SinOsc m => SinOsc c => dac; 2 => c.sync; //sync mode 2 tells SinOsc to interpret input as offset to the internal frequency cf 550 => float mf => m.freq; 300 => float cf => c.freq; 2 => float index; index * mf => m.gain; while( true ) 1::second => now;
and, if you are interested, the new ChubGraph feature in ChucK allows you to define new composite UGENS, which is handy here:
class MyFM extends Chubgraph { SinOsc m => SinOsc c => outlet; 2 => c.sync; //sync mode 2 tells SinOsc to interpret input as offset to the internal frequency cf //set some default values 550 => float mf => m.freq; 300 => float cf => c.freq; 2 => float index; index * mf => m.gain; fun float set_cf(float f) { f => cf => c.freq; return cf; } fun float set_mf(float f) { f => mf => m.freq; index * mf => m.gain; return mf; } fun float set_index(float f) { f => index; index * mf => m.gain; } fun void set_all(float newcf, float newmf, float newindex) { newcf => cf => c.freq; newmf => mf => m.freq; newindex => index; index * mf => m.gain; } } MyFM testfm => dac; 1::second => now; testfm.set_all(400, 250, 2.5); 1::second => now; //and now, add a 2nd, in parallel MyFM testfm2 => dac; 1::second => now;