Advertisement
SoundEngraver

FM Synthesis | FM Basics (Part 1)

Feb 3rd, 2023 (edited)
933
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.    ////////////////////////////// FM Basics | Part 1 //////////////////////////////
  2. //////////////////////////// WAVEFORMS AND CONTROL VALUES ///////////////////////////
  3.  
  4.  
  5. s.boot;
  6.  
  7. // Run these methods below for visual cues.
  8.  
  9. s.meter;
  10. s.scope;
  11. s.plotTree;
  12.  
  13. // I use the following only when necessary.
  14.  
  15. s.reboot;
  16. s.quit;
  17.  
  18. /////////////////////// Things To Know Before Running Code ///////////////////////
  19.  
  20. /*
  21.  
  22. All my original SC documents are in the "dracula" color.
  23. To find or change this, go To SuperCollider ––> Preferences ––> Editor ––> Font & Colors.
  24. ––> Select under Color, dracula.
  25.  
  26. Values presented in purple can be changed. Only remember to NEVER cross 0, when using an exponential method.
  27.  
  28. */
  29.  
  30.  
  31. // Types of Waveforms
  32.  
  33. {SinOsc.ar(300, 0, 0.2)!2}.play;
  34. {Saw.ar(300, 0.2)!2}.play;
  35. {LFSaw.ar(300, 0, 0.2)!2}.play;
  36. {LFTri.ar(300, 0, 0.2)!2}.play;
  37. {LFCub.ar(300, 0, 0.2)!2}.play;
  38. {LFPar.ar(300, 0, 0.2)!2}.play;
  39. {Pulse.ar(300, 0.5, 0.2)!2}.play;
  40. {LFPulse.ar(300, 0, 0.5, 0.2)!2}.play; // Don't forget the width argument!
  41.  
  42.  
  43. // SinOsc
  44.  
  45. {SinOsc.ar(200, 0, 0.2)!2}.play;
  46.  
  47. // Using a SinOsc with a Control Parameter (in this case, with XLine)
  48.  
  49. {SinOsc.ar(XLine.kr(2000, 200), 0, 0.2)!2}.play; // default dur value is 1 second
  50. {SinOsc.ar(XLine.kr(2000, 200, 8), 0, 0.2)!2}.play; // going from 2000Hz to 200Hz in 8 seconds
  51.  
  52.  
  53. // What's going here?
  54.  
  55. {SinOsc.ar(SinOsc.ar(XLine.kr(1, 20, 10), 0, 200, 400), 0, 0.2)!2}.play;
  56.  
  57. /* You have a sine tone at 400Hz, with a modulatory value of 200, meaning it will rise to 600Hz (400+200) and fall to 200Hz (400-200). Simultaneously, you have another control value with XLine, which traverses from 1 to 20 cycles per second over the course of 10 seconds. */
  58.  
  59. {SinOsc.ar(LFSaw.ar(XLine.kr(1, 20, 10), 0, 200, 400), 0, 0.2)!2}.play; // Same applies to sawtooth wave.
  60. {SinOsc.ar(LFTri.ar(XLine.kr(1, 20, 10), 0, 200, 400), 0, 0.2)!2}.play; // Same applies to triangle wave.
  61.  
  62. // Try having the sine tone at 800Hz for a perceptible difference.
  63. // The sine tone rises from its starting point at 800Hz to 1000Hz, before falling to 600Hz.
  64.  
  65. {SinOsc.ar(LFCub.ar(XLine.kr(1, 20, 10), 0, 200, 800), 0, 0.2)!2}.play;
  66. {SinOsc.ar(LFPar.ar(XLine.kr(1, 20, 10), 0, 200, 800), 0, 0.2)!2}.play;
  67.  
  68.  
  69. // Explore a larger ascending line, as seen here, from 1 to 100:
  70. {SinOsc.ar(SinOsc.ar(XLine.kr(1, 100, 10), 0, 200, 400), 0, 0.2)!2}.play;
  71.  
  72. // Note, this new tonal color still rests at 400.
  73. // Please consult this website seen below:
  74. // https://pages.mtu.edu/~suits/notefreqs.html
  75.  
  76.  
  77. // Saw
  78.  
  79. {Saw.ar(XLine.kr(20, 200, 8), 0.1)!2}.play;
  80.  
  81. {Saw.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.1)!2}.play; // no phase arg
  82. {Saw.ar(Saw.ar(XLine.kr(1, 20, 4), 200, 400), 0.1)!2}.play; // no phase arg for both Saw and XLine
  83. // At this point, I don't know what makes that perceivable descent in pitch. Notice this is exclusive to using two sawtooth waveforms.
  84.  
  85. {Saw.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.1)!2}.play; // include phase arg for LFSaw
  86. {Saw.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.1)!2}.play; // include phase arg for LFTri
  87. {Saw.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.1)!2}.play; // include phase arg for LFCub
  88. {Saw.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.1)!2}.play; // include phase arg for LFPar
  89.  
  90. // Please note: All arguments used for waveforms and XLine can be changed to your liking.
  91. // Don't change the 2 on "!2" unless you're working with multi-channel expansion. "!2" changes the mono signal to a stereo signal.
  92.  
  93. // LFSaw
  94.  
  95. {LFSaw.ar(XLine.kr(1, 100, 8), 0, 0.1)!2}.play; // needs phase arg
  96. {LFSaw.ar(Saw.ar(XLine.kr(1, 40, 8), 200, 400), 0, 0.1)!2}.play; // Remember, no phase for Saw, though we do see a phase value for LFSaw.
  97.  
  98. {LFSaw.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  99. {LFSaw.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  100. {LFSaw.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  101. {LFSaw.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  102. {LFSaw.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  103.  
  104.  
  105. // LFTri
  106.  
  107. {LFTri.ar(XLine.kr(100, 1000, 8), 0, 0.1)!2}.play;
  108.  
  109. {LFTri.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  110. {LFTri.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  111. {LFTri.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  112. {LFTri.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  113. {LFTri.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  114.  
  115. // Adding a control rate (".kr") to the control variable outputs the same.
  116. // For example:
  117.  
  118. {LFTri.ar(SinOsc.kr(XLine.kr(1, 20, 8), 0, 200, 400), 0, 0.1)!2}.play;
  119.  
  120. // That said, I would advise using the audio rate for higher frequencies and better resolution.
  121.  
  122.  
  123. // LFCub
  124.  
  125. {LFCub.ar(XLine.kr(100, 1000, 8), 0, 0.1)!2}.play;
  126.  
  127. {LFCub.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  128. {LFCub.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  129. {LFCub.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  130. {LFCub.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  131. {LFCub.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  132.  
  133.  
  134.  
  135. // LFPar
  136.  
  137. {LFPar.ar(XLine.kr(100, 1000, 8), 0, 0.1)!2}.play;
  138.  
  139. {LFPar.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  140. {LFPar.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  141. {LFPar.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  142. {LFPar.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  143. {LFPar.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.1)!2}.play;
  144.  
  145.  
  146. // Pulse (0.5 width value causes a square wave)
  147.  
  148. {Pulse.ar(XLine.kr(1, 100, 10), 0.5, 0.1)!2}.play; // Careful with the instigation of this. It clips.
  149. {Pulse.ar(XLine.kr(1, 1000, 10), 0.5, 0.1)!2}.play;
  150.  
  151. {Pulse.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.5, 0.1)!2}.play;
  152. {Pulse.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.5, 0.1)!2}.play;
  153. {Pulse.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.5, 0.1)!2}.play;
  154. {Pulse.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.5, 0.1)!2}.play;
  155. {Pulse.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0.5, 0.1)!2}.play;
  156.  
  157.  
  158. // LFPulse with Pulse...I'd probably not want to mess with this.
  159. // Sounds like R2-D2 before he's about to explode.
  160.  
  161.  
  162. // ...But LFPulse with other waveforms is good.
  163. // Remember: It needs a width argument!
  164.  
  165. {LFPulse.ar(XLine.kr(1, 100, 10), 0, 0.5, 0.1)!2}.play;
  166. {LFPulse.ar(XLine.kr(1, 1000, 10), 0, 0.5, 0.1)!2}.play;
  167.  
  168. {LFPulse.ar(SinOsc.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.5, 0.1)!2}.play;
  169. {LFPulse.ar(LFSaw.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.5, 0.1)!2}.play;
  170. {LFPulse.ar(LFTri.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.5, 0.1)!2}.play;
  171. {LFPulse.ar(LFCub.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.5, 0.1)!2}.play;
  172. {LFPulse.ar(LFPar.ar(XLine.kr(1, 20, 4), 0, 200, 400), 0, 0.5, 0.1)!2}.play;
  173.  
  174. // A couple things to note:
  175. // LFSaw outputs at a higher amplitude than Saw.
  176.  
  177.  
  178.  
  179. /////////////////////////////////////////////////////////////////////////
  180.  
  181. // More examples: (Here's the motion I personally had looked for.)
  182. // Replace XLine with a Wavetype.
  183.  
  184. {LFPar.ar(800, 0, 0.1)!2}.play;
  185.  
  186. {LFPar.ar(LFPar.kr(LFPar.kr(0.2, 0, 7, 10), 0, 200, 800), 0, 0.1)!2}.play;
  187. // Sine tone at 800Hz travels from 1000Hz to 600Hz, in the course of 5 seconds.
  188. // Simultaneously, you have a modulatory fluctuation from 10 to 3 cycles every 5 seconds.
  189. // 10-7 = 3. The integer 7 determines the lowest cycle value of the innermost parabolic oscillation.
  190.  
  191.  
  192. // Change values for a more dynamic motion.
  193.  
  194. {LFPar.ar(LFPar.kr(LFPar.kr(0.125, 0, 9.8, 10), 0, 200, 800), 0, 0.1)!2}.play;
  195. // Here, you have a dramatic change over the course of 8 seconds.
  196. // Remember: 1/0.125 = 8
  197. // Oscillator will modulate from 10 cycles to 0.2 cycles per second.
  198. // 10-9.8 = 0.2
  199.  
  200.  
  201. {LFPar.ar(LFPar.kr(LFPar.kr(0.2, 0, 3, 10), 0, 200, 800), 0, 0.1)!2}.play;
  202. // Based on the change to 3, can you guess what's going on?
  203. // Note how the difference isn't that dynamic.
  204.  
  205.  
  206. {LFPar.ar(LFPar.kr(0.2, 0, 400, 800), 0, 0.1)!2}.play; // begins on the highest frequency (1200Hz)
  207. // This is a sine tone at 800Hz traveling from 1200Hz to 400Hz in the course of 5 seconds.
  208. // Remember: 1/0.2 = 5
  209. // 800+400 = 1200; 800-400 = 400.
  210.  
  211.  
  212. // Compare:
  213.  
  214. {LFCub.ar(800, 0, 0.1)!2}.play;
  215.  
  216. {LFCub.ar(LFCub.kr(LFCub.kr(0.2, 0, 8, 10), 0, 400, 800), 0, 0.1)!2}.play;
  217. {LFCub.ar(LFCub.kr(0.2, 0, 400, 800), 0, 0.1)!2}.play; // LFCub begins at 800Hz before ascending to 1200Hz.
  218.  
  219. {SinOsc.ar(800, 0, 0.1)!2}.play;
  220.  
  221. {SinOsc.ar(SinOsc.kr(SinOsc.kr(0.2, 0, 8, 10), 0, 400, 800), 0, 0.1)!2}.play;
  222. {SinOsc.ar(SinOsc.kr(0.2, 0, 400, 800), 0, 0.1)!2}.play;
  223.  
  224. {LFTri.ar(800, 0, 0.1)!2}.play;
  225.  
  226. {LFTri.ar(LFTri.kr(LFTri.kr(0.2, 0, 8, 10), 0, 400, 800), 0, 0.1)!2}.play;
  227. {LFTri.ar(LFTri.kr(0.2, 0, 400, 800), 0, 0.1)!2}.play;
  228.  
  229. {LFPar.ar(LFPar.kr(LFPar.kr(0.2, 0, 8, 10), 0, 400, 800), 0, 0.1)!2}.play;
  230. {LFPar.ar(LFPar.kr(0.2, 0, 400, 800), 0, 0.1)!2}.play; // Notice how LFPar starts the signal at the highest frequency (1200Hz). Compare it to other waveforms again.
  231.  
  232. // Note: Mixing these waveforms in the syntax above doesn't output a huge perceptible difference. This may change with audio files of varying frequencies and their respective overtones. (See example below.)
  233.  
  234. {LFPar.ar(SinOsc.kr(LFTri.kr(0.2, 0, 8, 10), 0, 400, 800), 0, 0.1)!2}.play;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement