Cabbage Logo
Back to Cabbage Site

Primitive FM synth

This is my first Cabbage synth. I like to share it with the forum (and with the World ;-)). Everybody may do with it as they please. Comments about possible improvements or anything else are welcome. I want to learn more about building useful and fun Cabbage instrument plugins, and learning by doing seems to be a pleasant way to do so. Here it is:

<Cabbage>
form caption("Primitive FM-synth") size(800, 500), guiMode("queue"), pluginId("def1")

signaldisplay bounds(590, 30, 170, 140),   colour("lime"), displayType("waveform"),     signalVariable("aOutput")
signaldisplay bounds(590, 240, 170, 140),  colour("lime"), displayType("spectroscope"), signalVariable("aOutput")

keyboard bounds(20, 405, 750, 75)

rslider bounds(18, 30, 80, 80)   channel("vol")  range(0, 1, 0.5, 1, 0.001)          colour(255, 0, 0, 255) text("Volume")  textColour(255, 255, 0, 255)
rslider bounds(100, 30, 80, 80)  channel("att")  range(0.001, 0.25, 0.02, 1, 0.001)  colour(255, 0, 0, 255) text("Attack")  textColour(255, 245, 0, 255)
rslider bounds(180, 30, 80, 80)  channel("dec")  range(0.001, 0.25, 0.01, 1, 0.01)   colour(255, 0, 0, 255) text("Decay")   textColour(255, 245, 0, 255)
rslider bounds(260, 30, 80, 80)  channel("sus")  range(0, 1, 0.7, 1, 0.001)          colour(255, 0, 0, 255) text("Sustain") textColour(255, 245, 0, 255)
rslider bounds(340, 30, 80, 80)  channel("rel")  range(0, 1, 0.1, 1, 0.001)          colour(255, 0, 0, 255) text("Release") textColour(255, 245, 0, 255)

label bounds(20, 135, 400, 15) text("Carrier") colour(255, 255, 255, 225) fontColour(255, 0, 0, 255)

rslider bounds(20, 165, 80, 80)  channel("csin") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Sine")     textColour(255, 255, 0, 255) 
rslider bounds(100, 165, 80, 80) channel("csaw") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Saw")      textColour(255, 255, 0, 255)
rslider bounds(180, 165, 80, 80) channel("csqu") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Square")   textColour(255, 255, 0, 255)
rslider bounds(260, 165, 80, 80) channel("ctri") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Triangle") textColour(255, 255, 0, 255)
rslider bounds(340, 165, 80, 80) channel("cimp") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Impulse")  textColour(255, 255, 0, 255)

label bounds(20, 265, 400, 15) text("Modulator") colour(255, 255, 255, 255) fontColour(255, 0, 0, 255)

rslider bounds(20, 295, 80, 80)  channel("msin") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Sine")     textColour(255, 255, 0, 255) 
rslider bounds(100, 295, 80, 80) channel("msaw") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Saw")      textColour(255, 255, 0, 255)
rslider bounds(180, 295, 80, 80) channel("msqu") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Square")   textColour(255, 255, 0, 255)
rslider bounds(260, 295, 80, 80) channel("mtri") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Triangle") textColour(255, 255, 0, 255)
rslider bounds(340, 295, 80, 80) channel("mimp") range(0.001, 1, 0.2, 1, 0.001) colour(255, 0, 0, 255) text("Impulse")  textColour(255, 255, 0, 255)

rslider bounds(460, 30, 80, 80)  channel("modind")  range(0, 1000, 500, 1, 0.001)  colour(255, 0, 0, 255) text("Mod. index")  textColour(255, 255, 0, 255)
rslider bounds(460, 165, 80, 80) channel("freqrat") range(0, 5, 1, 1, 0.001)       colour(255, 0, 0, 255) text("Freq. ratio") textColour(255, 255, 0, 255) 
rslider bounds(460, 300, 80, 80) channel("fintun")  range(-0.1, 0.1, 0, 1, 0.001)  colour(255, 0, 0, 255) text("Fine-tuning") textColour(255, 255, 0, 255) 

</Cabbage>


<CsoundSynthesizer>

<CsOptions>
-m0d -n -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5 --displays 
</CsOptions>

<CsInstruments>

sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

instr 1
  giSin ftgen 0, 0, 2^10, 10, 1
  giSaw ftgen 0, 0, 2^10, 10, 1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9
  giSqu ftgen 0, 0, 2^10, 10, 1, 0, 1/3, 0, 1/5, 0, 1/7, 0, 1/9
  giTri ftgen 0, 0, 2^10, 10, 1, 0, -1/9, 0, 1/25, 0, -1/49, 0, 1/81
  giImp ftgen 0, 0, 2^10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1

  kVol chnget "vol"
  iAtt chnget "att"
  iDec chnget "dec"
  iSus chnget "sus"
  iRel chnget "rel"
      
  kCSin chnget "csin"
  kCSaw chnget "csaw"
  kCSqu chnget "csqu"
  kCTri chnget "ctri"
  kCImp chnget "cimp"
  
  kMSin chnget "msin"
  kMSaw chnget "msaw"
  kMSqu chnget "msqu"
  kMTri chnget "mtri"
  kMImp chnget "mimp"

  kModind  chnget "modind"
  kFreqrat chnget "freqrat"
  kFintun  chnget "fintun"

  kRat = kFreqrat + kFintun
  aModulatorSin poscil p5, p4*kRat, giSin
  aModulatorSaw poscil p5, p4*kRat, giSaw
  aModulatorSqu poscil p5, p4*kRat, giSqu
  aModulatorTri poscil p5, p4*kRat, giTri
  aModulatorImp poscil p5, p4*kRat, giImp
  
  kSumM = kMSin + kMSaw + kMSqu + kMTri + kMImp
  aModulator = (kMSin*aModulatorSin + kMSaw*aModulatorSaw + kMSqu*aModulatorSqu + kMTri*aModulatorTri + kMImp*aModulatorImp)/kSumM

  aCarrierSin poscil p5, p4 + kModind*aModulator, giSin
  aCarrierSaw poscil p5, p4 + kModind*aModulator, giSaw 
  aCarrierSqu poscil p5, p4 + kModind*aModulator, giSqu
  aCarrierTri poscil p5, p4 + kModind*aModulator, giTri
  aCarrierImp poscil p5, p4 + kModind*aModulator, giImp
 
  kADSR madsr iAtt, iDec, iSus, iRel
  kSumC =  kCSin + kCSaw + kCSqu + kCTri + kCImp
  aOutput = kADSR*kVol*(kCSin*aCarrierSin + kCSaw*aCarrierSaw + kCSqu*aCarrierSqu + kCTri*aCarrierTri + kCImp*aCarrierImp)/kSumC 

  out aOutput, aOutput
  display aOutput, .1, 1 
  dispfft aOutput, .1, 1024
endin

</CsInstruments>

<CsScore>
;causes Csound to run for about 7000 years...
f0 z
</CsScore> 

</CsoundSynthesizer>

Thanks for sharing. Iā€™m always impressed by the range of sounds FM gives.

1 Like

This is the GUI:

1 Like

Really nice. I am not working with FM normally and it is a great help to see the waveform and spectrum immediately showing the effect of the controls. Great instrument to learn and experiment!

1 Like

Thank you for your comment! Building the instrument was a great learning experience for me, and seeing others happily using it is a great motivation to build some more.