to demistify the two approaches:
The two windows i have been using for either of the approaches are nearly identical in behaviour and have one common feature, they collapse to 1 if the index is 0.
(
var raisedCos = { |phase, index|
var cosine = cos(phase * 2pi);
exp(index.abs * (cosine - 1));
};
var gaussianWindow = { |phase, index|
var halfCosCycle = sin(phase * pi) * index;
exp(halfCosCycle.neg * halfCosCycle);
};
{
var index = 2;
var rate = 100;
var phase = Phasor.ar(DC.ar(0), rate * SampleDur.ir);
var sigA = raisedCos.(phase, index);
var sigB = gaussianWindow.(phase, index);
[sigA * cos(phase * 2pi), sigB * cos(phase * 2pi)];
}.plot(0.02);
)
with the mod FM you have control over the bandwidth via the index and the harmonics independently, but the spectrum is always harmonic:
(
var crossfade_formants = { |phase, harm|
var harm_even = harm.round(2);
var harm_odd = ((harm + 1).round(2) - 1);
var sig_even = cos(phase * 2pi * harm_even);
var sig_odd = cos(phase * 2pi * harm_odd);
XFade2.ar(sig_even, sig_odd, harm.fold(0, 1) * 2 - 1);
};
var raisedCos = { |phase, index|
var cosine = cos(phase * 2pi);
exp(index.abs * (cosine - 1));
};
{
var freq, phase, harmonic, index, gaussWindow, formants, sig;
freq = \freq.kr(440);
phase = Phasor.ar(DC.ar(0), freq * SampleDur.ir);
harmonic = MouseX.kr(1, 10);
index = MouseY.kr(0, 10);
gaussWindow = raisedCos.(phase, index);
formants = crossfade_formants.(phase, harmonic);
sig = formants * gaussWindow;
sig = LeakDC.ar(sig);
sig!2 * 0.1;
}.play;
)
with the single sideband PM approach the bandwidth and the harmonics are controlled both via the index, but you can additionally create inharmonic sounds by adjusting the modRatio:
(
var raisedCos = { |phase, index|
var cosine = cos(phase * 2pi);
exp(index.abs * (cosine - 1));
};
{
var carrFreq, modFreq, carrPhase, modPhase, index;
var gaussWindow, mod, carr, sig;
carrFreq = \freq.kr(440);
modFreq = carrFreq * MouseY.kr(1, 2);
carrPhase = Phasor.ar(DC.ar(0), carrFreq * SampleDur.ir);
modPhase = Phasor.ar(DC.ar(0), modFreq * SampleDur.ir);
index = MouseX.kr(0, 30);
gaussWindow = raisedCos.(modPhase, index);
mod = sin(modPhase * 2pi);
carr = sin(carrPhase * 2pi + (mod * index));
sig = carr * gaussWindow;
sig = LeakDC.ar(sig);
sig!2 * 0.1;
}.play;
)
you decide what suits your needs!