Advertisement
SoundEngraver

FM Synthesis | FM Basics (Part 5)

Mar 11th, 2023 (edited)
805
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /////////////////////// FM SYNTHESIS | FM Basics (Part 5) ///////////////////////
  2. /////////////////////////////// Sound Files ////////////////////////////////
  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.  
  19. // Part 5 continues with the code established in Part 4, but with Sound Files.
  20.  
  21. ////////////////// Things To Know Before Running Code //////////////////
  22.  
  23. /*
  24.  
  25. All my original SC documents are in the "dracula" color.
  26. To find or change this, go To SuperCollider ––> Preferences ––> Editor ––> Font & Colors.
  27. ––> Select under Color, dracula.
  28.  
  29. Arguments in Synths are represented with a backslash, "\", in green under the "dracula" color font.
  30. Values presented with these arguments can be changed. Only remember to NEVER cross 0, when using an exponential method like "exprand."
  31.  
  32. Arguments also precede a colon ":", as seen in a list of a UGen following a variable, "var."
  33. Example: sig = PlayBuf.ar(2, buf, rate, startPos: spos);
  34.  
  35. Argument and variable names can be changed to your liking.
  36.  
  37. Please be careful with volume output. Always have SuperCollider run through headphones. If you're unsure what the output will be, keep headphones away, with your main volume all the way down. Check your level meter and Stethoscope for visual cues. If everything looks safe (e.g. level meter is NOT in the red), proceed.
  38.  
  39. You can always execute a hard stop with Command Period.
  40.  
  41. */
  42.  
  43. ///////////////////////  Syntax For Locating Sound Files In Folders ///////////////////////
  44.  
  45. ~bufPath = PathName.new(thisProcess.nowExecutingPath).parentPath ++ "drone"; // <-- insert your sound folder, in place of where my "drone" folder is. Your folder can have any name.
  46.  
  47. // Here's another folder with 3 of my sound files.
  48.  
  49. ~bufPath1 = PathName.new(thisProcess.nowExecutingPath).parentPath ++ "ambient";
  50.  
  51. (
  52. b = PathName.new(~bufPath).entries.collect({
  53.     arg pathname;
  54.     Buffer.read(s, pathname.fullPath);
  55. });
  56. )
  57.  
  58. (
  59. c = PathName.new(~bufPath1).entries.collect({
  60.     arg pathname;
  61.     Buffer.read(s, pathname.fullPath);
  62. });
  63. )
  64.  
  65. // Make sure your sound files play back. You should see in on the scope and level meters.
  66.  
  67. // I have 3 files in my "ambient" Folder. Thus, I have below: c[0], c[1], and c[2].
  68. // 0, being the first sound file indexed in my Folder.
  69.  
  70. b[0].play;
  71. b[0].duration;
  72.  
  73. c[0].play;
  74. c[1].play;
  75. c[2].play;
  76.  
  77. // All these are 20 seconds.
  78.  
  79. c[0].duration;
  80. c[1].duration;
  81. c[2].duration;
  82.  
  83.  
  84. // SynthDefs
  85.  
  86. Env([0, 1, 0], [0.1, 3], [1, -5]).plot; // Envelope shape to reference.
  87. // First array, [0, 1, 0], are levels.
  88. // Second array, [0.1, 3], are times traversing between levels.
  89. // Third array, [1, -5], are curve values.
  90.  
  91.  
  92. // What's happening here? (Hint: We've covered this line of code in FM Basics, Parts 1 & 4.)
  93.  
  94. {LFPar.ar(LFPar.kr(LFPar.kr(0.2, 0, 8, 10), 0, 200, 800), 0, 0.1)!2}.play;
  95. // Execute a hard stop with Command Period.
  96.  
  97.  
  98. // You have two Parabolic Oscillators working as controls for a Parabolic audio signal.
  99. // {LFPar.ar(), 0, 0.1)}, the outermost part of the Function, is the signal.
  100.  
  101. // The two innermost oscillators perform the following:
  102.  
  103. // Sine tone at 800Hz travels to 1000Hz, then to 600Hz, in the course of 5 seconds.
  104. // 800+200=1000; 800-200=600Hz.
  105. // Simultaneously, you have a modulatory fluctuation from 10 to 2 cycles every 5 seconds.
  106. // 10-8=2. The integer 8 determines the lowest cycle value of the innermost parabolic oscillator.
  107.  
  108.  
  109. // Integrate this into a SynthDef.
  110.  
  111. // IMPORTANT: Keep amp values low when experimenting. You can always increase the amp value after hearing the Synth.
  112.  
  113. (
  114. SynthDef.new(\sinSine, {
  115.     arg out=0;
  116.     var sig;
  117.     sig = LFPar.ar(LFPar.kr(LFPar.kr(0.25, 0, 8, 10), 0, 200, 800), 0, 0.1);
  118.     sig = sig!2; // You will not need this for a stereo sound file.
  119.     Out.ar(out, sig);
  120. }).add;
  121. )
  122.  
  123. Synth(\sinSine);
  124. // Execute hard stop with Command Period.
  125.  
  126.  
  127. // Now, for a sound file, you will only one Control signal (e.g. one LFPar) for the audio signal.
  128. // Thus, I'm using only 2 LFPar UGens. By the way, you can use other UGen oscillators, though I'd avoid Pulse.
  129.  
  130. (
  131. SynthDef.new(\sineSound, {
  132.     arg buf=0, rate=1, spos=0, amp=1, pan=0, out=0;
  133.     var sig, par;
  134.     par = LFPar.ar(LFPar.kr(0.25, 0, 8, 10), 0, 0.5); // 0.5 is the mul value, which is scaling the output by one half.
  135.     sig = PlayBuf.ar(
  136.         2,
  137.         buf,
  138.         BufRateScale.kr(buf) * rate,
  139.         spos
  140.     );
  141.     sig = sig * par;
  142.     sig = Pan2.ar(sig, pan, amp);
  143.     Out.ar(out, sig);
  144. }).add;
  145. )
  146.  
  147. Synth(\sineSound, [\buf, b[0]]);
  148.  
  149. // Command Period, or wait until the sound file is released at the end of its duration.
  150. // NOTE: If you only have one sound file in a Folder, the code can be:
  151. Synth(\sineSound, [\buf, 0]); // Notice, I do not include here the global variable, "b".
  152.  
  153.  
  154. Synth(\sineSound, [\buf, c[0], \amp, rrand(0.8, 1)]);
  155. // Go between c[0], c[1], and c[2]...if you have 3 sound files, like I have.
  156.  
  157.  
  158. // IMPORTANT: Notice the Synths have not freed themselves. Let's work with an Envelope.
  159.  
  160.  
  161. // Add an Envelope
  162.  
  163. Env([0, 1, 0], [0.1, 8], [1, -2]).plot;
  164.  
  165. // Here's another way of writing out the arguments.
  166. // Check PlayBuf in the Help browser, in order to see the designated argument names.
  167.  
  168. (
  169. SynthDef.new(\sineSound1, {
  170.     arg buf=0, rate=1, spos=0, amp=1, pan=0,
  171.     atk=0.1, rel=8, c1=1, c2=(-5), out=0;
  172.     var sig, par, env;
  173.     env = Env([0, 1, 0], [atk, rel], [c1, c2]).kr(2);
  174.     par = LFPar.ar(LFPar.kr(0.25, 0, 8, 10), 0, 0.8);
  175.     sig = PlayBuf.ar(
  176.         numChannels: 2,
  177.         bufnum: buf,
  178.         rate: BufRateScale.kr(buf) * rate,
  179.         startPos: spos
  180.     );
  181.     sig = sig * par * env;
  182.     sig = Pan2.ar(sig, pan, amp);
  183.     Out.ar(out, sig);
  184. }).add;
  185. )
  186.  
  187. Synth(\sineSound1, [\buf, b[0]]); // Synth releases after 8 seconds.
  188. Synth(\sineSound1, [\buf, c[0], \rel, rrand(8, 12)]);
  189.  
  190.  
  191. // Add argument names to change argument values in real time.
  192. // Keep in mind, you don't need to name these in any particular order.
  193.  
  194. (
  195. SynthDef.new(\sineSound2, {
  196.     arg buf=0, rate=1, spos=0, atk=0.1, rel=12, c1=1, c2=(-5),
  197.     parCtrl=0.25, parMin=8, parMax=10, addCtrl=0.8,
  198.     amp=1, pan=0, out=0;
  199.     var sig, par, env;
  200.     env = Env([0, 1, 0], [atk, rel], [c1, c2]).kr(2);
  201.     par = LFPar.ar(LFPar.kr(parCtrl, 0, parMin, parMax), 0, addCtrl);
  202.     sig = PlayBuf.ar(
  203.         numChannels: 2,
  204.         bufnum: buf,
  205.         rate: BufRateScale.kr(buf) * rate,
  206.         startPos: spos
  207.     );
  208.     sig = sig * par * env;
  209.     sig = Pan2.ar(sig, pan, amp);
  210.     Out.ar(out, sig);
  211. }).add;
  212. )
  213.  
  214. Synth(\sineSound2, [\buf, b[0]]);
  215. Synth(\sineSound2, [\buf, c[2]]);
  216.  
  217.  
  218. // Add Arguments
  219. // For \buf, go between Folders, if applicable (e.g. \buf, b[0], \buf, c[0], \buf, c[1], \buf, c[2]).
  220.  
  221.  
  222. (
  223. Synth(\sineSound2, [
  224.     \buf, c[2],
  225.     \amp, rrand(0.1, 1),
  226.     \atk, rrand(0.1, 1),
  227.     \rel, rrand(2, 8),
  228.     \c1, rrand(1, 4),
  229.     \c2, rrand(-1, -5),
  230.     \parCtrl, rrand(0.125, 4),
  231.     \parMin, rrand(3, 8),
  232.     \parMax, rrand(9, 10),
  233.     \addCtrl, rrand(0.1, 1),
  234. ]);
  235. )
  236.  
  237.  
  238. // Add the "midiratio" method to change the pitch of sound files.
  239. // 0.midiratio is the original pitch. In my example, this is Middle C.
  240. // +1 is up a half step; -1 is down a half step. Use the rate argument for this (e.g. \rate, 3.midiratio).
  241.  
  242.  
  243. (
  244. Synth(\sineSound2, [
  245.     \buf, c[2],
  246.     \rate, rrand(0, 24).midiratio,
  247.     \amp, rrand(0.1, 1),
  248.     \atk, rrand(0.001, 0.1),
  249.     \rel, rrand(10, 20),
  250.     \c1, rrand(1, 4),
  251.     \c2, rrand(-1, -3),
  252.     \parCtrl, rrand(0.125, 0.5),
  253.     \parMin, rrand(5, 8),
  254.     \parMax, rrand(9, 10),
  255.     \addCtrl, rrand(0.5, 1),
  256. ]);
  257. )
  258.  
  259.  
  260.   --------------------------------------------------------------------------------
  261. //////////////////////////////////////  Slower Motion //////////////////////////////////////
  262.  
  263. {LFPar.ar(LFPar.kr(0.2, 0, 400, 800), 0, 0.1)!2}.play;
  264. // Execute hard stop with Command Period.
  265.  
  266.  
  267. // SynthDef Version
  268.  
  269. (
  270. SynthDef.new(\slowSine, {
  271.     arg out=0;
  272.     var sig;
  273.     sig = LFPar.ar(LFPar.kr(0.2, 0, 400, 800), 0, 0.1);
  274.     sig = sig!2;
  275.     Out.ar(out, sig);
  276. }).add;
  277. )
  278.  
  279. Synth(\slowSine);
  280.  
  281. // Add an Envelope, Arguments, and Sound Files
  282. // Note: Applying these values don't make the sound file aurally that interesting. This is because the FM values are more perceptible than the nature of the sound file.
  283.  
  284. (
  285. SynthDef.new(\slowSine, {
  286.     arg buf=0, rate=1, spos=0, atk=0.1, rel=8, c1=1, c2=(-5),
  287.     parCtrl=0.25, parMin=400, parMax=800,
  288.     parAmp=0.5, amp=1, pan=0, out=0;
  289.     var sig, par, env;
  290.     env = Env([0, 1, 0], [atk, rel], [c1, c2]).kr(2);
  291.     par = LFPar.ar(LFPar.kr(parCtrl, 0, parMin, parMax), 0, parAmp);
  292.     sig = PlayBuf.ar(
  293.         2,
  294.         buf,
  295.         BufRateScale.kr(buf) * rate,
  296.         spos
  297.     );
  298.     sig = sig * par * env;
  299.     sig = Pan2.ar(sig, pan, amp);
  300.     Out.ar(out, sig);
  301. }).add;
  302. )
  303.  
  304. Synth(\slowSine, [\buf, b[0]]);
  305.  
  306. (
  307. Synth(\slowSine, [
  308.     \buf, c[2],
  309.     \rate, rrand(0, 12).midiratio, // Ranges between original pitch and 1 octave higher.
  310.     \amp, rrand(0.5, 0.8),
  311.     \atk, rrand(0.001, 0.1),
  312.     \rel, rrand(8, 20),
  313.     \c1, rrand(1, 4),
  314.     \c2, rrand(-1, -2),
  315.     \parCtrl, rrand(0.125, 0.5),
  316.     \parMin, rrand(100, 200),
  317.     \parMax, rrand(400, 800),
  318.     \parAmp, rrand(0.3, 0.8)
  319. ]);
  320. )
  321.  
  322. // Keep modulatory values low, if you want to perceive more the Sound File and less FM.
  323.  
  324. (
  325. Synth(\slowSine, [
  326.     \buf, c[2],
  327.     \rate, rrand(0, 12).midiratio,
  328.     \amp, rrand(0.8, 1),
  329.     \atk, rrand(0.001, 0.1),
  330.     \rel, rrand(8, 20),
  331.     \c1, rrand(1, 4),
  332.     \c2, rrand(-1, -2),
  333.     \parCtrl, rrand(0.125, 0.5),
  334.     \parMin, rrand(10, 20), // I suggest not exceeding 20, to have a better effect.
  335.     \parMax, rrand(400, 500),
  336.     \parAmp, rrand(0.5, 1)
  337. ]);
  338. )
Tags: fm synthesis
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement