electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software » ChucK programming language
FM Synthesis in Chuck
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [4 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
Render787



Joined: Jun 06, 2007
Posts: 2
Location: Pasadena, CA

PostPosted: Wed Jun 06, 2007 9:32 am    Post subject: FM Synthesis in Chuck
Subject description: Any hints on how to do it?
Reply with quote  Mark this post and the followings unread

Hi all,

I am trying to figure out how to do FM Synthesis ala Sound Blaster, using Chuck. I don't have great experience using filters, but it seems like it shouldn't be hard to do, especially given an ADSR envelope already present in the STK...

My understanding of FM synthesis comes from this document, and from what I remember of screwing around with my Sound Blaster when I was a kid:

http://ccrma.stanford.edu/software/snd/snd/fm.html

http://www.shipbrook.com/jeff/sb.html

The deal seems to be that you have a "carrier" signal and a "modulator" signal. These each have A,D,S,R numbers... so that suggests two ADSR envelopes... and you plug the modulator into the carrier. And I guess you drive it with a sinosc, or some white noise, or something... Right?

Except this example on the chuck wiki does something much more complicated, doing essentially sample-by-sample computation of the formula on the site I found above:

http://wiki.cs.princeton.edu/forums.html/ChucK/fm.ck

Also, I tried writing up my idea below, and I'm not entirely sure it sounds right:

Code:


SinOsc s => ADSR modulator => ADSR carrier => dac;

.5 => s.gain;
Std.mtof(60)=> s.freq;

/*
Sound Blaster hex #'s for a BASSGUITAR: (F means fastest, 0 means slowest for ADR, 0 means loudest and F softest for S)

modulator AD = 0xF1
modulator SR = 0x11
carrier AD = 0x11
carrier SR = 0xB3
*/

modulator.set( 2::ms , 100::ms, .9, 750::ms);
carrier.set( 100::ms, 100::ms, .7, 500::ms);

36 => int i;

while ( true )
{
    Std.mtof(i) => s.freq;

    modulator.keyOn();
    carrier.keyOn();
    <<<"on note =", i>>>;
    500::ms => now;

    modulator.keyOff();
    carrier.keyOff();
    <<<"off">>>;
    1000::ms => now;
   
    1 +=> i;
    36 -=> i;
    37 %=> i;
    36 +=> i;
}



I suspect that the way this is set up now, the modulator is not actually "modulating" the frequency of the carrier. Can anyone confirm this, and maybe point my in the right direction?

Thanks.
Back to top
View user's profile Send private message
Render787



Joined: Jun 06, 2007
Posts: 2
Location: Pasadena, CA

PostPosted: Wed Jun 06, 2007 2:42 pm    Post subject: Reply with quote  Mark this post and the followings unread

So I looked through the forum again... I thought I had searched for FM, but apparently this post of Kijjaz's didn't turn up... oops.

http://electro-music.com/forum/post-112986.html#112986

The bottom part of this post seems to show how to do at least some version of FM. I didn't realize that SinOsc, PulseOsc, etc. had inputs! What is the meaning of these inputs? From the context, I would assume it just adds it to the current time when computing the output... Nifty.

This doesn't use the ADSR stuff from Sound Blaster though. So I would assume that your final set up will look like:

Code:

SinOsc modulator => ADSR modulator_stuff => SinOsc carrier => ADSR carrier_stuff => dac;


The example in this post isn't clear on what the frequencies of the modulator and carrier represent though.

I guess the multiplier in Kijjaz's post is the "mc-ratio" referred to in this site?
http://ccrma.stanford.edu/software/snd/snd/fm.html

Is that the same as the "modulator frequency multiple" referred to in the Sound Blaster FM specs? (bytes 20-35)
http://www.shipbrook.com/jeff/sb.html

If so then I guess that ratio is a critical number in defining an instrument using this system as well as just the ADSR parameters. The Sound Blaster specs page seems to describe this number as only really affecting the sound by producing an octave shift... I guess maybe there are other consequences as well.

Hmm... Please let me know if anything I'm suggesting here doesn't make sense.

I guess I am generally unclear on what are the results in terms of waveshaping when you use an Oscilator as a filter. I get the highpass, lowpass, etc. idea. Does using an Oscilator as a filter create a time-varying filter? Or is it that an Oscilator with no input uses time as the input, and with something chucked to it as input, it uses the amplitude of that input in place of the variable for time?

Thanks.[/code]
Back to top
View user's profile Send private message
chuckles



Joined: Apr 02, 2007
Posts: 72
Location: San Diego, California

PostPosted: Thu Jun 07, 2007 9:21 am    Post subject: Reply with quote  Mark this post and the followings unread

What I did was to try some simple things first to help me understand:

From fm2.ck:

Code:
// FM using sinosc

// modulator to carrier
SinOsc m => SinOsc c => dac;

// carrier frequency
220 => c.freq;

// modulator frequency
550 => m.freq;

// gain of modulator is also called FM index of modulation
200 => m.gain;

// phase modulation is FM synthesis (sync is 2)
2 => c.sync;

// time-loop
while( true )
{
    1::second => now;
}


or modifying the ring.ck example:

Code:
// ring-to-fm.ck
//
// any ugen has .op which can be:
// ---
// -1 pass through the input
//  0 stop input
//  1 add inputs (default)
//  2 subtract from first input
//  3 multiply inputs
//  4 divide from first input
//--------------------------------------------

//  a basic patch
SinOsc f1 => Gain g => dac;
SinOsc f2 => g;

// multiply inputs at g
3 => g.op;

400.0 => f1.freq;
150.0 => f2.freq;
1 => f2.gain; // experiment with changing this from 0 to
                    // several hundred, e.g.

// time loop
while( true )
    1::second => now;


My apologies if this is all stuff you've already been through, but I wondered if you might be overly complicating things...

<<<c>>>
Back to top
View user's profile Send private message
kijjaz



Joined: Sep 20, 2004
Posts: 765
Location: bangkok, thailand
Audio files: 4

PostPosted: Fri Jun 08, 2007 3:52 am    Post subject: Reply with quote  Mark this post and the followings unread

Render787 wrote:

Code:

SinOsc modulator => ADSR modulator_stuff => SinOsc carrier => ADSR carrier_stuff => dac;


The example in this post isn't clear on what the frequencies of the modulator and carrier represent though.

I guess the multiplier in Kijjaz's post is the "mc-ratio" referred to in this site?
http://ccrma.stanford.edu/software/snd/snd/fm.html

...

Thanks.[/code]


Oh! Thanks and welcome to the club .. hahah Very Happy
And it's so nice you're experimenting FM
it's a fun thing to do.
i'm not very good at FM sound design but been doing on chuck sometimes now ^_^

I'll tell more about the patching you mentioned.

And this will be mainly creating FM in ChucK alone,
so it won't have anything to do with Soundblaster's features.

Ok.. let's take a look at an oscillator..
say SinOsc

Code:
SinOsc carrier => dac;
0.4 => carrier.gain;
2::second => now;


This is just playing the sine oscillator plainly.
If we want to add two signals from two oscillators together,
we'd do this:

Code:
SinOsc s1 => dac;
SinOsc s2 => dac;
0.4 => s1.gain => s2.gain; // set gain of each osc to 40%
220 => s1.freq; // set frequency of s1
550 => s2.freq; // set frequency of s2
2::second => now;


But now, there are some ways we can play with the "input" of an oscillator.
Connecting a signal directly into an oscillator without adjusting its .sync value..
make the inputs set the 'frequency' of the oscillator..

For example if we chuck a 'Step' to a 'SinOsc',
we can just set the SinOsc's frequency by setting the Step's value.
(by using Step's next)

Code:
Step freq => SinOsc s => dac;
220 => freq.next;
1::second => now;
550 => freq.next;
1::second => now;


But how about we add an oscillator to modulate the SinOsc's frequency?
(thus creating the sin(freq.t + B.sin(modfreq.t)) in the FM theory)

Code:
Step carrierfreq => SinOsc s => dac; // make carrierfreq the main frequency
SinOsc mod => s; // add an oscillating signal to the frequency of s;
220 => carrierfreq.next; // set the carrier frequency to 220hz
550 => mod.freq; // set the frequency of the modulating signal
300 => mod.gain; // set the 'depth' of the modulation
// i'm not sure is this the mc-ratio you're talking about..

2::second => now;


Try changing the carrier freq's value, modulation signal frequency, and modulation depth and see the effect
of sine wave FMing a sine wave..

But there's a more convenient way in ChucK..
a basic oscillator such as SinOsc SqrOsc TriOsc SawOsc...
or Phaser...
all have this option: .sync

you can set .sync to 0 (default) <-- the input signal will set the frequency of the oscillator
(just like we see above)

or set .sync to 1 <-- the input signal will set the phase of the oscillator
(let's just skip this one)

or set .sync to 2 <-- the input signal will actually ADD to the oscillator's current frequency!

so .sync number 2 would set the mode of the oscillator to FM right away
and you can just hook up two oscillators to create FM..

Code:
SinOsc modulator => SinOsc carrier => dac;
2 => carrier.sync; // use carrier's input to modulate its frequency
330 => modulator.freq; // modulator's frequency
500 => modulator.gain; // modulation depth
220 => carrier.freq; // carrier's frequency

2::second => now;


this would give the same kind of FM you experienced above
but with a more compact code.

The ADSR you see in what I wrote there
is how we can use Envelope to set the amplitude of some signal..
so it can be inserted:
After the modulator <-- to use the envelope to adjust 'modulation depth'
After the carrier <-- ti use the envelope to adjust 'carrier amplitude'

This is quite a basic way to create analog FM synth sound
let's chat more about FMing sometimes! ..
Back to top
View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [4 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » ChucK programming language
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use