phase modulation and hard sync?
Hi, new to chuck here. Can SinOsc be hard synced by an impulse or something? And how would you do phase modulation with SinOsc? If you cannot do one or both with SinOsc, how would you do it? thanks
Hello, Alexandre, good to see you here (you don't know me but I know your
work)!
SinOsc has .phase and .sync attributes, which are pretty useful in this
case. I made a very
dirty and arbitrary example to show this working (using .sync, in this
case):
// *pmod* is the SinOsc which will modulate the phase of *main*
SinOsc pmod => SinOsc main => dac;
440 => main.freq;
// define index of modulation; it's fun to fiddle with this value!
50 => pmod.gain;
// set *main* to sync phase-wise with *pmod*'s input
// just in case: 0 = sync frequency to input; 1 = sync phase; 2 = FM!
1 => main.sync;
// loop to show phase modulation in action with random arbitrary values
while(true) {
Math.random2f(63, 880) => pmod.freq;
1::second => now;
}
You can also do everything "by hand", mapping arbitrary values directly
into SinOsc's .phase attribute.
Hope it helps!
Cheers!
Em sex, 2 de jun de 2017 às 19:21, Alexandre Torres Porres
Hi, new to chuck here.
Can SinOsc be hard synced by an impulse or something?
And how would you do phase modulation with SinOsc?
If you cannot do one or both with SinOsc, how would you do it?
thanks _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
Hi Jean, nice to meet and thanks for your help. I'm still having a hard
time figuring this out. Let's try separate examples for both phase mod and
sync, how about that?
What puzzles me is the sync argument of SinOsc, it's not clear how it
works, and I haven't found a good description or examples of it in the
documentation. Maybe there is some and I missed it.
So, I was trying to do either phase modulation or hard sync, and couldn't
do it. Allow me to simplify your code and then I'll ask more questions.
// ==========================
// *mod* is the SinOsc which will modulate the phase of *carrier*
SinOsc mod => SinOsc carrier => dac;
440 => carrier.freq; // set carrier frequency
1 => mod.gain; // set modulation index
// set *carrier* oscillator to sync phase-wise with *mod*'s input
// just in case: 0 = sync frequency to input; 1 = sync phase; 2 = FM!
1 => carrier.sync;
// set modulation frequency
while(true) {
100 => mod.freq;
1::second => now;
}
// ==========================
So, question 1) About "1 => carrier.sync"; I don't get it. Why if I remove
it I don't have phase modultion or any sound at all?
Question 2) Why changing the carrier frequency seems to have no effect?
So, let's compare to a simple phase modulation code in SuperCollider;
{SinOsc.ar(201, SinOsc.ar(50), 2pi) ! 2}.play
In SuperCollider, the phase input is in radians, hence, I'm setting the
modulation index to 6.28 (2pi). Don't know how the phase is scaled in
Chuck. But if it is linear, such as in Pd/Max, it should be "1" instead.
Anyway, how to achieve the same result as the SuperCollider code?
thanks
2017-06-03 12:43 GMT-03:00 Jean Menezes da Rocha
Hello, Alexandre, good to see you here (you don't know me but I know your work)!
SinOsc has .phase and .sync attributes, which are pretty useful in this case. I made a very dirty and arbitrary example to show this working (using .sync, in this case):
// *pmod* is the SinOsc which will modulate the phase of *main* SinOsc pmod => SinOsc main => dac;
440 => main.freq;
// define index of modulation; it's fun to fiddle with this value! 50 => pmod.gain;
// set *main* to sync phase-wise with *pmod*'s input // just in case: 0 = sync frequency to input; 1 = sync phase; 2 = FM! 1 => main.sync;
// loop to show phase modulation in action with random arbitrary values while(true) { Math.random2f(63, 880) => pmod.freq; 1::second => now; }
You can also do everything "by hand", mapping arbitrary values directly into SinOsc's .phase attribute.
Hope it helps!
Cheers!
Em sex, 2 de jun de 2017 às 19:21, Alexandre Torres Porres < porres@gmail.com> escreveu:
Hi, new to chuck here.
Can SinOsc be hard synced by an impulse or something?
And how would you do phase modulation with SinOsc?
If you cannot do one or both with SinOsc, how would you do it?
thanks _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Alexandre,
As far as I understand it, the .sync attribute is more like an identifier,
rather than a true numeric value (that is, 0 says you are syncing frequency
with frequency; 1 says that you are syncing phase with frequency; 2 says
you are doing true Frequency Modulation). As you are telling that no value
means no sound, one can infer that there is no default value for that, and
if you are feeding UGen => UGen, telling which is your sync method is
mandatory (but I can be mistaken, as usual).
As for your second question, my understanding of Phase Modulation (as
explained here https://en.wikipedia.org/wiki/Phase_modulation) is that
the carrier wave is supposed to be stationary frequency-wise, so this is
the expected behavior. What creates the effect of modulation is the
modulator's *amplitude* over the carrier's *phase*. There is a nice graphic
illustrating this here
https://commons.wikimedia.org/wiki/File:Phase-modulation.gif#/media/File:Pha...
.
ChucK's UGen documentation tells that the .phase value is a floating-point
number, which seems to be linear. As for the SinOsc object, it should be
cycled through a sine function (thus always keeping values between -1.0 and
1.0). In such case, very roughly put, the original phase is always 0, and
you can shift from a full cycle to the left (-1) through to a full cycle to
the right (+1).
I am probably missing some fine detail here, and hopefully someone with
more solid knowledge of ChucK's internals will provide you with a more
technical explanation. Unfortunately, my knowledge of SuperCollider is very
limited and I don't feel like I'm able to translate your code.
I will try and prepare some better example later when I have my computer
around.
Best regards!
Em sáb, 3 de jun de 2017 às 14:07, Alexandre Torres Porres
Hi Jean, nice to meet and thanks for your help. I'm still having a hard time figuring this out. Let's try separate examples for both phase mod and sync, how about that?
What puzzles me is the sync argument of SinOsc, it's not clear how it works, and I haven't found a good description or examples of it in the documentation. Maybe there is some and I missed it.
So, I was trying to do either phase modulation or hard sync, and couldn't do it. Allow me to simplify your code and then I'll ask more questions.
// ==========================
// *mod* is the SinOsc which will modulate the phase of *carrier*
SinOsc mod => SinOsc carrier => dac;
440 => carrier.freq; // set carrier frequency
1 => mod.gain; // set modulation index
// set *carrier* oscillator to sync phase-wise with *mod*'s input
// just in case: 0 = sync frequency to input; 1 = sync phase; 2 = FM!
1 => carrier.sync;
// set modulation frequency
while(true) {
100 => mod.freq;
1::second => now;
}
// ==========================
So, question 1) About "1 => carrier.sync"; I don't get it. Why if I remove it I don't have phase modultion or any sound at all?
Question 2) Why changing the carrier frequency seems to have no effect?
So, let's compare to a simple phase modulation code in SuperCollider;
{SinOsc.ar(201, SinOsc.ar(50), 2pi) ! 2}.play
In SuperCollider, the phase input is in radians, hence, I'm setting the modulation index to 6.28 (2pi). Don't know how the phase is scaled in Chuck. But if it is linear, such as in Pd/Max, it should be "1" instead.
Anyway, how to achieve the same result as the SuperCollider code?
thanks
2017-06-03 12:43 GMT-03:00 Jean Menezes da Rocha
:
Hello, Alexandre, good to see you here (you don't know me but I know your work)!
SinOsc has .phase and .sync attributes, which are pretty useful in this case. I made a very dirty and arbitrary example to show this working (using .sync, in this case):
// *pmod* is the SinOsc which will modulate the phase of *main* SinOsc pmod => SinOsc main => dac;
440 => main.freq;
// define index of modulation; it's fun to fiddle with this value! 50 => pmod.gain;
// set *main* to sync phase-wise with *pmod*'s input // just in case: 0 = sync frequency to input; 1 = sync phase; 2 = FM! 1 => main.sync;
// loop to show phase modulation in action with random arbitrary values while(true) { Math.random2f(63, 880) => pmod.freq; 1::second => now; }
You can also do everything "by hand", mapping arbitrary values directly into SinOsc's .phase attribute.
Hope it helps!
Cheers!
Em sex, 2 de jun de 2017 às 19:21, Alexandre Torres Porres < porres@gmail.com> escreveu:
Hi, new to chuck here.
Can SinOsc be hard synced by an impulse or something?
And how would you do phase modulation with SinOsc?
If you cannot do one or both with SinOsc, how would you do it?
thanks _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha
Alexandre,
As far as I understand it, the .sync attribute is more like an identifier, rather than a true numeric value (that is, 0 says you are syncing frequency with frequency; 1 says that you are syncing phase with frequency; 2 says you are doing true Frequency Modulation). As you are telling that no value means no sound, one can infer that there is no default value for that, and if you are feeding UGen => UGen, telling which is your sync method is mandatory (but I can be mistaken, as usual).
there may be a default parameter, right? And that seems to be 0. If I have sync at "0", I hear no sound. Anyway, it doesn't seem like the sync parameter is able to do hard sync. It seemed that the "0" value would do that, but, as I said, I hear nothing. If phase input is linear in chuck, then the code from SuperCollider would be equivalent, but it is not. And even if it wasn't linear, I tried it with radian values and did not get the same results. I suspect it is not really doing phase modulation because it doesn't matter if I change the carrier frequency, and that is weird. well, I guess I'm repeating myself, sorry, just anxious in the hope of clarification. thanks
2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha
Unfortunately, my knowledge of SuperCollider is very limited and I don't feel like I'm able to translate your code.
Here's an attempt to make SC code clearer.
Here's the fm example I found in chuck, using sync = 2
////////////////////////////////////////////////////
SinOsc m => SinOsc c => dac; // modulator to carrier
400 => c.freq; // carrier frequency
201 => m.freq; // modulator frequency
1500 => m.gain; // modulation index
2 => c.sync; // FM synthesis (sync is 2)
while( true ) 1::second => now; // time-loop
////////////////////////////////////////////////////
And now for the SC equivalent
////////////////////////////////////////////////////
{var carrier = 400; // carrier frequency
var modulator = 201; // modulator frequency
var index = 1500; // modulation index
var m = SinOsc.ar(modulator) * index; // modulating signal
var c = SinOsc.ar(carrier + m); // frequency modulation (carrier +
modulating signal)
Out.ar (0, c ! 2)}.play
////////////////////////////////////////////////////
and now a phase modulation example in SC
////////////////////////////////////////////////////
{var carrier = 400; // carrier frequency
var modulator = 201; // modulator frequency
var index = 2pi; // modulation index
var m = SinOsc.ar(modulator) * index; // modulating signal
var c = SinOsc.ar(carrier, m); // frequency modulation (carrier +
modulating signal)
Out.ar (0, c ! 2)}.play
////////////////////////////////////////////////////
note, the SinOsc in SuperCollider takes frequency input as the first
variable in parenthesis, and phase (in radians) in the second.
cheers
2017-06-03 15:31 GMT-03:00 Alexandre Torres Porres
2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha
:
Alexandre,
As far as I understand it, the .sync attribute is more like an identifier, rather than a true numeric value (that is, 0 says you are syncing frequency with frequency; 1 says that you are syncing phase with frequency; 2 says you are doing true Frequency Modulation). As you are telling that no value means no sound, one can infer that there is no default value for that, and if you are feeding UGen => UGen, telling which is your sync method is mandatory (but I can be mistaken, as usual).
there may be a default parameter, right? And that seems to be 0. If I have sync at "0", I hear no sound.
Anyway, it doesn't seem like the sync parameter is able to do hard sync. It seemed that the "0" value would do that, but, as I said, I hear nothing.
If phase input is linear in chuck, then the code from SuperCollider would be equivalent, but it is not. And even if it wasn't linear, I tried it with radian values and did not get the same results.
I suspect it is not really doing phase modulation because it doesn't matter if I change the carrier frequency, and that is weird.
well, I guess I'm repeating myself, sorry, just anxious in the hope of clarification.
thanks
Alexandre,
the thing is that SuperCollider does the iteration stuff automatically for
you. In ChucK you have to iterate manually to achieve the same effect. I
think your SuperCollider example could adapt as follows:
SinOsc car;
SinOsc mod;
400 => car.freq;
201 => mod.freq;
2 * Math.PI => float ind => mod.gain; // I don't know if using PI is
relevant here, or linear values between -1 and 1 would suffice!
car => dac;
mod => blackhole;
while ( true ) {
ind * mod.last() => car.phase;
1::samp => now;
}
I think advancing time at sample level is the key, as we are using .last()
to get accurate values from the modulator. Anyways it indeed does not
respond to changes in the carrier's frequency, which is not what you
expect. Changing the modulator's frequency, however, does effectively
change the resulting sound. I honestly don't know if this is just a plain
difference to each language's approach, or if ChucK has another method to
hard sync stuff that we are missing here.
Please observe that in this example we are not using the .sync parameter;
instead we are mapping values for every sample directly to the carrier's
.phase parameter.
Unfortunately I don't have SC installed here so I cannot compare results.
Please let me know.
Good luck!
Em sáb, 3 de jun de 2017 às 19:04, Alexandre Torres Porres
2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha
:
Unfortunately, my knowledge of SuperCollider is very limited and I don't feel like I'm able to translate your code.
Here's an attempt to make SC code clearer.
Here's the fm example I found in chuck, using sync = 2
////////////////////////////////////////////////////
SinOsc m => SinOsc c => dac; // modulator to carrier
400 => c.freq; // carrier frequency
201 => m.freq; // modulator frequency
1500 => m.gain; // modulation index
2 => c.sync; // FM synthesis (sync is 2)
while( true ) 1::second => now; // time-loop
////////////////////////////////////////////////////
And now for the SC equivalent
////////////////////////////////////////////////////
{var carrier = 400; // carrier frequency
var modulator = 201; // modulator frequency
var index = 1500; // modulation index
var m = SinOsc.ar(modulator) * index; // modulating signal
var c = SinOsc.ar(carrier + m); // frequency modulation (carrier + modulating signal)
Out.ar (0, c ! 2)}.play
////////////////////////////////////////////////////
and now a phase modulation example in SC
////////////////////////////////////////////////////
{var carrier = 400; // carrier frequency
var modulator = 201; // modulator frequency
var index = 2pi; // modulation index
var m = SinOsc.ar(modulator) * index; // modulating signal
var c = SinOsc.ar(carrier, m); // frequency modulation (carrier + modulating signal)
Out.ar (0, c ! 2)}.play
////////////////////////////////////////////////////
note, the SinOsc in SuperCollider takes frequency input as the first variable in parenthesis, and phase (in radians) in the second.
cheers
2017-06-03 15:31 GMT-03:00 Alexandre Torres Porres
: 2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha < jean@menezesdarocha.info>:
Alexandre,
As far as I understand it, the .sync attribute is more like an identifier, rather than a true numeric value (that is, 0 says you are syncing frequency with frequency; 1 says that you are syncing phase with frequency; 2 says you are doing true Frequency Modulation). As you are telling that no value means no sound, one can infer that there is no default value for that, and if you are feeding UGen => UGen, telling which is your sync method is mandatory (but I can be mistaken, as usual).
there may be a default parameter, right? And that seems to be 0. If I have sync at "0", I hear no sound.
Anyway, it doesn't seem like the sync parameter is able to do hard sync. It seemed that the "0" value would do that, but, as I said, I hear nothing.
If phase input is linear in chuck, then the code from SuperCollider would be equivalent, but it is not. And even if it wasn't linear, I tried it with radian values and did not get the same results.
I suspect it is not really doing phase modulation because it doesn't matter if I change the carrier frequency, and that is weird.
well, I guess I'm repeating myself, sorry, just anxious in the hope of clarification.
thanks
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
I managed to install SuperCollider and run your example of Phase Modulation. I could achieve the exact same sound with the following ChucK code: SinOsc mod => SinOsc car => dac; 400 => car.freq; 201 => mod.freq; mod.freq() * Math.PI => float ind => mod.gain; // this bugger works with much greater values as standard gain... 2 => car.sync; // FM instead of syncing to phase. don't know why... while ( true ) { 1::second => now; } The weird thing is that I had to use 2 (FM) as a value for .sync, contrary to my intuition of syncing to phase. Another oddity is the way to calculate the modulation index, which I admit was a wild guess that turned out to be correct. I am also curious if anyone can explain this. Anyways, the example above sounded exactly like your SC code, and now it responds to changes in the carrier signal, which was what you wanted at first place. However, I am now the one struggling to figure out the difference between this phase modulation and FM, since the method used had to be the same as used for Frequency Modulation... syncing to phase, as was my first intuition, yields a rather different sound (much harsher) and does not respond to changes to the carrier's frequency. Hope it can get you going, anyways! Em sáb, 3 de jun de 2017 às 23:36, Jean Menezes da Rocha < jean@menezesdarocha.info> escreveu:
Alexandre,
the thing is that SuperCollider does the iteration stuff automatically for you. In ChucK you have to iterate manually to achieve the same effect. I think your SuperCollider example could adapt as follows:
SinOsc car; SinOsc mod;
400 => car.freq; 201 => mod.freq; 2 * Math.PI => float ind => mod.gain; // I don't know if using PI is relevant here, or linear values between -1 and 1 would suffice!
car => dac; mod => blackhole;
while ( true ) { ind * mod.last() => car.phase; 1::samp => now; }
I think advancing time at sample level is the key, as we are using .last() to get accurate values from the modulator. Anyways it indeed does not respond to changes in the carrier's frequency, which is not what you expect. Changing the modulator's frequency, however, does effectively change the resulting sound. I honestly don't know if this is just a plain difference to each language's approach, or if ChucK has another method to hard sync stuff that we are missing here. Please observe that in this example we are not using the .sync parameter; instead we are mapping values for every sample directly to the carrier's .phase parameter. Unfortunately I don't have SC installed here so I cannot compare results. Please let me know.
Good luck!
Em sáb, 3 de jun de 2017 às 19:04, Alexandre Torres Porres < porres@gmail.com> escreveu:
2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha < jean@menezesdarocha.info>:
Unfortunately, my knowledge of SuperCollider is very limited and I don't feel like I'm able to translate your code.
Here's an attempt to make SC code clearer.
Here's the fm example I found in chuck, using sync = 2
////////////////////////////////////////////////////
SinOsc m => SinOsc c => dac; // modulator to carrier
400 => c.freq; // carrier frequency
201 => m.freq; // modulator frequency
1500 => m.gain; // modulation index
2 => c.sync; // FM synthesis (sync is 2)
while( true ) 1::second => now; // time-loop
////////////////////////////////////////////////////
And now for the SC equivalent
////////////////////////////////////////////////////
{var carrier = 400; // carrier frequency
var modulator = 201; // modulator frequency
var index = 1500; // modulation index
var m = SinOsc.ar(modulator) * index; // modulating signal
var c = SinOsc.ar(carrier + m); // frequency modulation (carrier + modulating signal)
Out.ar (0, c ! 2)}.play
////////////////////////////////////////////////////
and now a phase modulation example in SC
////////////////////////////////////////////////////
{var carrier = 400; // carrier frequency
var modulator = 201; // modulator frequency
var index = 2pi; // modulation index
var m = SinOsc.ar(modulator) * index; // modulating signal
var c = SinOsc.ar(carrier, m); // frequency modulation (carrier + modulating signal)
Out.ar (0, c ! 2)}.play
////////////////////////////////////////////////////
note, the SinOsc in SuperCollider takes frequency input as the first variable in parenthesis, and phase (in radians) in the second.
cheers
2017-06-03 15:31 GMT-03:00 Alexandre Torres Porres
: 2017-06-03 15:01 GMT-03:00 Jean Menezes da Rocha < jean@menezesdarocha.info>:
Alexandre,
As far as I understand it, the .sync attribute is more like an identifier, rather than a true numeric value (that is, 0 says you are syncing frequency with frequency; 1 says that you are syncing phase with frequency; 2 says you are doing true Frequency Modulation). As you are telling that no value means no sound, one can infer that there is no default value for that, and if you are feeding UGen => UGen, telling which is your sync method is mandatory (but I can be mistaken, as usual).
there may be a default parameter, right? And that seems to be 0. If I have sync at "0", I hear no sound.
Anyway, it doesn't seem like the sync parameter is able to do hard sync. It seemed that the "0" value would do that, but, as I said, I hear nothing.
If phase input is linear in chuck, then the code from SuperCollider would be equivalent, but it is not. And even if it wasn't linear, I tried it with radian values and did not get the same results.
I suspect it is not really doing phase modulation because it doesn't matter if I change the carrier frequency, and that is weird.
well, I guess I'm repeating myself, sorry, just anxious in the hope of clarification.
thanks
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
2017-06-04 0:47 GMT-03:00 Jean Menezes da Rocha
I managed to install SuperCollider and run your example of Phase Modulation. I could achieve the exact same sound with the following ChucK code:
SinOsc mod => SinOsc car => dac;
400 => car.freq; 201 => mod.freq; mod.freq() * Math.PI => float ind => mod.gain; // this bugger works with much greater values as standard gain... 2 => car.sync; // FM instead of syncing to phase. don't know why...
while ( true ) { 1::second => now; }
It might sound the same, or similar, but this is still frequency modulation and not phase modulation.
The weird thing is that I had to use 2 (FM) as a value for .sync, contrary to my intuition of syncing to phase.
Again, not weird, just a fact that Frequency and Phase modulation are related
Another oddity is the way to calculate the modulation index, which I admit was a wild guess that turned out to be correct. I am also curious if anyone can explain this.
It's not easy to explain, but you found the magic number/formula that makes Frequency modulation sound like Phase Modulation.
However, I am now the one struggling to figure out the difference between this phase modulation and FM
In short, they behave differently with the same parameters, but the parameters can be "converted"/"adjusted" to sound the same.
syncing to phase, as was my first intuition, yields a rather different sound (much harsher) and does not respond to changes to the carrier's frequency.
Yep, as I noted, and it is not actually doing phase modulation Hence, a working phase modulation code still remains mysterious to me. It seems that when you have a phase input to SinOsc, it'll only consider that input and disregard any frequency input, is that possible? Perhaps you can just feed a phase input to SinOsc and then modulate that signal. Like, send it a phasor input and modulate it. That's gotta work. cheers
On 06/04/2017 12:35 AM, Alexandre Torres Porres wrote:
It seems that when you have a phase input to SinOsc, it'll only consider that input and disregard any frequency input, is that possible?
Yes, that is correct. IIRC, doesn't cyclone have some oscillators that work that way as well? Joel
2017-06-04 2:46 GMT-03:00 Joel Matthys
On 06/04/2017 12:35 AM, Alexandre Torres Porres wrote:
It seems that when you have a phase input to SinOsc, it'll only consider that input and disregard any frequency input, is that possible?
Yes, that is correct. IIRC, doesn't cyclone have some oscillators that work that way as well?
The only oscillator with a phase input in cyclone (or max) is cycle~ it has a frequency input in the left inlet and a phase input in the right inlet. But sending a phase signal to drive cycle~ does not anule the phase input at all! And this is what I'm suspecting it's happening in Chuck, and what you seem to be confirming to me. Phasor p => SinOsc osc => dac; 440 => p.freq; // 440 => osc.freq; 1 => osc.sync; 4::second => now; In the above code, I have a Phasor driving the oscillator, and the same result as if I had a SinOsc with the same frequency as the Phasor's frequency... Now, if I uncomment the line "// 440 => osc.freq;", nothing changes! As if the frequency input is anuled or something. Going back to cycle~, the two input are valid, and the result is that the output frequency is 880 hz (the sum of both inputs). Now, that makes phase modulation extremely trivial and simple with cycle~ I know I'm close to doing it in Chuck, If uncommenting that line in the code did work, I'd be done with it, but I'm stuck... Is it really impossible to set both a frequency value and a phase input from another Unit Generator? If not, then adding a signal to the Phasor output has got to do the job. But how can you do that? cheers
But sending a phase signal to drive cycle~ does not anule the phase input at all!
I meant to say it does not anule the FREQUENCY input at all!
2017-06-04 3:22 GMT-03:00 Alexandre Torres Porres
2017-06-04 2:46 GMT-03:00 Joel Matthys
: On 06/04/2017 12:35 AM, Alexandre Torres Porres wrote:
It seems that when you have a phase input to SinOsc, it'll only consider that input and disregard any frequency input, is that possible?
Yes, that is correct. IIRC, doesn't cyclone have some oscillators that work that way as well?
The only oscillator with a phase input in cyclone (or max) is cycle~
it has a frequency input in the left inlet and a phase input in the right inlet.
But sending a phase signal to drive cycle~ does not anule the phase input at all! And this is what I'm suspecting it's happening in Chuck, and what you seem to be confirming to me.
Phasor p => SinOsc osc => dac;
440 => p.freq;
// 440 => osc.freq;
1 => osc.sync;
4::second => now;
In the above code, I have a Phasor driving the oscillator, and the same result as if I had a SinOsc with the same frequency as the Phasor's frequency...
Now, if I uncomment the line "// 440 => osc.freq;", nothing changes! As if the frequency input is anuled or something.
Going back to cycle~, the two input are valid, and the result is that the output frequency is 880 hz (the sum of both inputs).
Now, that makes phase modulation extremely trivial and simple with cycle~
I know I'm close to doing it in Chuck, If uncommenting that line in the code did work, I'd be done with it, but I'm stuck...
Is it really impossible to set both a frequency value and a phase input from another Unit Generator?
If not, then adding a signal to the Phasor output has got to do the job. But how can you do that?
cheers
2017-06-04 2:35 GMT-03:00 Alexandre Torres Porres
It's not easy to explain, but you found the magic number/formula that makes Frequency modulation sound like Phase Modulation.
Actually, I shouldn't have said this, I don't wanna give you the idea it comes down to this, but there are just too many details I didn't want get into, sorry. What I can say is that you got pretty close, not 100% there yet, and that is not as simple as just doing this every time, it gets more complicated. Sorry again for not getting into the math and everything. What I'd like to add is that people use phase modulation instead of trying to replicate it via frequency modulation cause it's just more convenient to do directly via phase modulation if you want it to behave like that. cheers
Alexandre,
I have translated a PD patch (see the last graph on this page
http://pd-tutorial.com/english/ch03s06.html) and it is modulating AND
responding to frequency changes. See if this does the trick for you
(doesn't sound exactly like your SC code, but I think some fiddling with
modulation index can be useful):
Step imp; // now I am using an impulse to generate sound after calculating
stuff from phasor/sinosc
Phasor carrier; // Miller said to do so ;)
SinOsc modul; // a phasor as carrier, a sinosc as modulator
Gain g; // this object serves only to sum the signals
1 => g.op; // op number 1 is sum.
400 => carrier.freq;
201 => modul.freq;
1 => float ind => modul.gain; // so, modul. signal * index + carrier signal.
imp => dac; // impulse is actually generating sound
carrier => g => blackhole; // both generators go through a Gain object an
then to the blackhole
modul => g; // so that they only lend data to the Impulse generator
while ( true ) { // this loop includes a timed function only to show that
this stuff responds to changes into carrier's frequency
now + 1::second => time later;
while (now < later) {
Math.cos(g.last()) => imp.next; // i am running this through a
Cosine function since Phasor is a ramp (let's smooth that)
1::samp => now;
}
if ( maybe ) 20 + carrier.freq() => carrier.freq;
else -30 + carrier.freq() => carrier.freq;
}
Please notice that Miller Puckette's approach includes using the phasor as
*carrier* and sinosc as *modulator*, so that we can separate phase
treatment and wave generation (phasor + cos). I am using an Impulse
generator in order to be allowed to pass the resulting signal through the
cosine function before sending it to DAC.
Keep trying...
Em dom, 4 de jun de 2017 às 03:34, Alexandre Torres Porres
2017-06-04 2:35 GMT-03:00 Alexandre Torres Porres
: It's not easy to explain, but you found the magic number/formula that makes Frequency modulation sound like Phase Modulation.
Actually, I shouldn't have said this, I don't wanna give you the idea it comes down to this, but there are just too many details I didn't want get into, sorry. What I can say is that you got pretty close, not 100% there yet, and that is not as simple as just doing this every time, it gets more complicated.
Sorry again for not getting into the math and everything. What I'd like to add is that people use phase modulation instead of trying to replicate it via frequency modulation cause it's just more convenient to do directly via phase modulation if you want it to behave like that.
cheers
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
2017-06-04 4:16 GMT-03:00 Jean Menezes da Rocha
Alexandre,
I have translated a PD patch (see the last graph on this page http://pd-tutorial.com/english/ch03s06.html) and it is modulating AND responding to frequency changes.
cool, but we're not in fact using a frequency input here. It's more having a carrier phase signal plus a modulating signal. Just saying it cause I still would like a definitive word on an oscillator being able to set both frequency and phase. I'm really curious about it now. Moreover, this code seems a little more complicated than I expected. There's gotta be an easier way. The thing with the Pd patch is that Pd Vanilla's [osc~] does not have a phase input, so it is not using the input on an oscillator in order to modulate its phase, but a cosine function - [cos~]. It'd be much simpler if you used an external like [cycle~]. If you used the right inlet of [cycle~] instead of [cos~], you'd get the same result. Since SinOsc in chuck has a phase input, you do not need to use a cosine function like the Pd patch, but just sum the phasor and the oscillator and then feed it to the phase input (sync = 1). That oughta simplify things a lot. Even more simple would be if SinOsc could take a frequency input and also accept a signal to modulate it's phase input. Then you wouldn't need a phasor as the carrier signal, just a frequency value. But that is out of question, huh? cheers
so, this is my attempt to make it simpler, having a phasor and a sine wave
summed together, then fed into the phase input of an oscillator.
but since I never used chuck, I always screw it up, this doesn't work, but
it should be easy to fix
Phasor carrier;
SinOsc mod;
Gain sum;
1 => sum.op; // Gain's op number 1 is sum
400 => carrier.freq;
201 => mod.freq;
1 => float ind => mod.gain; // modulation index
mod => sum;
carrier => sum => SinOsc => dac;
1 => osc.sync;
4::second => now;
2017-06-04 4:16 GMT-03:00 Jean Menezes da Rocha
Alexandre,
I have translated a PD patch (see the last graph on this page http://pd-tutorial.com/english/ch03s06.html) and it is modulating AND responding to frequency changes. See if this does the trick for you (doesn't sound exactly like your SC code, but I think some fiddling with modulation index can be useful):
Step imp; // now I am using an impulse to generate sound after calculating stuff from phasor/sinosc Phasor carrier; // Miller said to do so ;) SinOsc modul; // a phasor as carrier, a sinosc as modulator Gain g; // this object serves only to sum the signals 1 => g.op; // op number 1 is sum.
400 => carrier.freq; 201 => modul.freq; 1 => float ind => modul.gain; // so, modul. signal * index + carrier signal.
imp => dac; // impulse is actually generating sound carrier => g => blackhole; // both generators go through a Gain object an then to the blackhole modul => g; // so that they only lend data to the Impulse generator
while ( true ) { // this loop includes a timed function only to show that this stuff responds to changes into carrier's frequency now + 1::second => time later; while (now < later) { Math.cos(g.last()) => imp.next; // i am running this through a Cosine function since Phasor is a ramp (let's smooth that) 1::samp => now; } if ( maybe ) 20 + carrier.freq() => carrier.freq; else -30 + carrier.freq() => carrier.freq; }
Please notice that Miller Puckette's approach includes using the phasor as *carrier* and sinosc as *modulator*, so that we can separate phase treatment and wave generation (phasor + cos). I am using an Impulse generator in order to be allowed to pass the resulting signal through the cosine function before sending it to DAC.
Keep trying...
Em dom, 4 de jun de 2017 às 03:34, Alexandre Torres Porres < porres@gmail.com> escreveu:
2017-06-04 2:35 GMT-03:00 Alexandre Torres Porres
: It's not easy to explain, but you found the magic number/formula that makes Frequency modulation sound like Phase Modulation.
Actually, I shouldn't have said this, I don't wanna give you the idea it comes down to this, but there are just too many details I didn't want get into, sorry. What I can say is that you got pretty close, not 100% there yet, and that is not as simple as just doing this every time, it gets more complicated.
Sorry again for not getting into the math and everything. What I'd like to add is that people use phase modulation instead of trying to replicate it via frequency modulation cause it's just more convenient to do directly via phase modulation if you want it to behave like that.
cheers
-- Jean Menezes da Rocha Compositor Professor Doutorando em Música pela Universidade Federal da Bahia
Hi Alexandre, about FM and PM (probably my reply is late!), here's a simple implementation using oscillators with sync(0): /// m = mod osc; c = carrier osc;// //SinOsc m => Gain g => SinOsc c => dac;// //Step cm => g; //cm = carrier freq in Hz// // // //while( true ){// // modInd(10, 250); //arg: modInd, freq mod // // cm.next(500);////carrier frequency // second => now;// //}// // //fun void modInd( float i, float f ){ //arg: modInd, freq mod// // float am; // // // i*f => am; //(modInd = Am/Fm), then (Am = modInd*Fm)// // m.freq(f);// // m.gain(am);// //}/ this is the simplest modulation, that usually is considered as FM, but in the end is a PM. without going into details, what's happening is: FM (t)=sin(ω c t +Φ c + I sin (ω m t +Φ m )) with ω c = carrier freq, ω m = mod freq, Φ = phase Cheers, Mario On 04/06/17 07:34, Alexandre Torres Porres wrote:
2017-06-04 2:35 GMT-03:00 Alexandre Torres Porres
mailto:porres@gmail.com>: It's not easy to explain, but you found the magic number/formula that makes Frequency modulation sound like Phase Modulation.
Actually, I shouldn't have said this, I don't wanna give you the idea it comes down to this, but there are just too many details I didn't want get into, sorry. What I can say is that you got pretty close, not 100% there yet, and that is not as simple as just doing this every time, it gets more complicated.
Sorry again for not getting into the math and everything. What I'd like to add is that people use phase modulation instead of trying to replicate it via frequency modulation cause it's just more convenient to do directly via phase modulation if you want it to behave like that.
cheers
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2017-06-04 4:24 GMT-03:00 mario buoninfante
this is the simplest modulation, that usually is considered as FM, but in the end is a PM.
Well, as I see it, it should be either FM or PM, it can't be one but in the end is something else. And your code is can only (not usually) be considered FM. But it seems you're saying both are related, without getting into details - which is something we've already discussed here, and I've also pointed out (with no details either). But the bottom line is that they're different, and the same input parameters generate different results. Though I've said before the parameters can be "converted"/"adjusted" to sound the same. Namely, the same modulation index does not generate the same result (Jean noticed that), and I can add the detail that the same modulating signal/waveform generate different results too. For example, a triangular wave modulating the phase is the same as a square wave modulating the frequency. So, they're quite different. In terms of sine waves, what we've been doing so far, if you modulate the phase with a sine wave, you need to modulate the frequency with a cosine wave. Like I pointed before, if you're going for a phase modulation implementation, you should just modulate the phase instead of trying to replicate it via frequency modulation, cause it's just more convenient to do directly via phase modulation if you want it to behave like that. And that noted, several FM modules are not actually implemented via frequency modulation, but phase modulation (i.e DX7 and native's instruments FM8). Anyway, performing FM in Chuck is easy and straightforward, it was never a question. The relationship between FM and PM was known and does not really mean they're both the same thing. Hence, there's still a need to quest for an easy implementation of phase modulation. cheers
btw, for adjusting the index, you're just multiplying the frequency to the
index, you should also multiply it by 2pi (like Jean found out by accident).
2017-06-04 12:29 GMT-03:00 Alexandre Torres Porres
2017-06-04 4:24 GMT-03:00 mario buoninfante
: this is the simplest modulation, that usually is considered as FM, but in the end is a PM.
Well, as I see it, it should be either FM or PM, it can't be one but in the end is something else. And your code is can only (not usually) be considered FM.
But it seems you're saying both are related, without getting into details - which is something we've already discussed here, and I've also pointed out (with no details either). But the bottom line is that they're different, and the same input parameters generate different results. Though I've said before the parameters can be "converted"/"adjusted" to sound the same.
Namely, the same modulation index does not generate the same result (Jean noticed that), and I can add the detail that the same modulating signal/waveform generate different results too. For example, a triangular wave modulating the phase is the same as a square wave modulating the frequency. So, they're quite different.
In terms of sine waves, what we've been doing so far, if you modulate the phase with a sine wave, you need to modulate the frequency with a cosine wave.
Like I pointed before, if you're going for a phase modulation implementation, you should just modulate the phase instead of trying to replicate it via frequency modulation, cause it's just more convenient to do directly via phase modulation if you want it to behave like that.
And that noted, several FM modules are not actually implemented via frequency modulation, but phase modulation (i.e DX7 and native's instruments FM8).
Anyway, performing FM in Chuck is easy and straightforward, it was never a question. The relationship between FM and PM was known and does not really mean they're both the same thing.
Hence, there's still a need to quest for an easy implementation of phase modulation.
cheers
there may be a default parameter, right? And that seems to be 0. If I have sync at "0", I hear no sound.
I think "sync" is a poor keyword for this method. It has nothing to do with hard sync. Instead, it determines what to do with a UGen connected to its input. This: SinOsc a => SinOsc b => dac; 0 => b.sync; // the default results in no audio because ChucK is attempting to use the output of SinOsc a (which is of course a stream between -1 and 1) and using those values as the frequency parameter for SinOsc b. In other words, SinOsc b is playing at a frequency between -1 and 1. Here's a demonstration of how sync 0 can work: Phasor p => SinOsc b => dac; 1 => p.freq; 1000 => p.gain; 0.25 => b.gain; 4::second => now;
Anyway, it doesn't seem like the sync parameter is able to do hard sync. It seemed that the "0" value would do that, but, as I said, I hear nothing.
I think you're right; to do hard sync you have to manually check the Phasor and reset the oscillator phase. BTW, according to the source code, the .phase method ranges from [0-1). Phasor p => blackhole; SinOsc s => dac; 0.2 => s.gain; 440 => s.freq; 1 => p.freq; spork~ hardsync(); while (true) { second => now; p.freq() + 1 => p.freq; } fun void hardsync() { float prev; while (true) { p.last() => float last; if (last < prev) 0 => s.phase; last => prev; samp => now; } }
If phase input is linear in chuck, then the code from SuperCollider would be equivalent, but it is not. And even if it wasn't linear, I tried it with radian values and did not get the same results.
I suspect it is not really doing phase modulation because it doesn't matter if I change the carrier frequency, and that is weird.
well, I guess I'm repeating myself, sorry, just anxious in the hope of clarification.
thanks
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Thanks joel, it's starting to make sense to me now.
I'd suggest more examples in the documentation explaining what this sync
parameter is and works so it's clearer
cheers
2017-06-04 0:53 GMT-03:00 Joel Matthys
there may be a default parameter, right? And that seems to be 0. If I have sync at "0", I hear no sound.
I think "sync" is a poor keyword for this method. It has nothing to do with hard sync. Instead, it determines what to do with a UGen connected to its input.
This: SinOsc a => SinOsc b => dac; 0 => b.sync; // the default
results in no audio because ChucK is attempting to use the output of SinOsc a (which is of course a stream between -1 and 1) and using those values as the frequency parameter for SinOsc b. In other words, SinOsc b is playing at a frequency between -1 and 1.
Here's a demonstration of how sync 0 can work:
Phasor p => SinOsc b => dac; 1 => p.freq; 1000 => p.gain; 0.25 => b.gain; 4::second => now;
Anyway, it doesn't seem like the sync parameter is able to do hard sync. It seemed that the "0" value would do that, but, as I said, I hear nothing.
I think you're right; to do hard sync you have to manually check the Phasor and reset the oscillator phase. BTW, according to the source code, the .phase method ranges from [0-1).
Phasor p => blackhole; SinOsc s => dac; 0.2 => s.gain; 440 => s.freq; 1 => p.freq;
spork~ hardsync();
while (true) { second => now; p.freq() + 1 => p.freq; }
fun void hardsync() { float prev; while (true) { p.last() => float last; if (last < prev) 0 => s.phase; last => prev; samp => now; } }
If phase input is linear in chuck, then the code from SuperCollider would be equivalent, but it is not. And even if it wasn't linear, I tried it with radian values and did not get the same results.
I suspect it is not really doing phase modulation because it doesn't matter if I change the carrier frequency, and that is weird.
well, I guess I'm repeating myself, sorry, just anxious in the hope of clarification.
thanks
_______________________________________________ chuck-users mailing listchuck-users@lists.cs.princeton.eduhttps://lists.cs.princeton.edu/mailman/listinfo/chuck-users
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
participants (4)
-
Alexandre Torres Porres
-
Jean Menezes da Rocha
-
Joel Matthys
-
mario buoninfante