You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.7KB

  1. /*
  2. Simple synthesizer with one oscillator, LFO and envelope.
  3. Author: Leonardo Laguna Ruiz - leonardo@vult-dsp.com
  4. Check the API documentation in the basic.vult example
  5. */
  6. fun env(gate) {
  7. mem x;
  8. val k = if gate > x then 0.05 else 0.0002;
  9. x = x + (gate - x) * k;
  10. return x;
  11. }
  12. fun edge(x):bool {
  13. mem pre_x;
  14. val v:bool = (pre_x <> x) && (pre_x == false);
  15. pre_x = x;
  16. return v;
  17. }
  18. fun pitchToFreq(cv) {
  19. return 261.6256 * exp(cv * 0.69314718056);
  20. }
  21. fun phasor(pitch, reset){
  22. mem phase;
  23. val rate = pitchToFreq(pitch) * sampletime();
  24. phase = phase + rate;
  25. if(phase > 1.0)
  26. phase = phase - 1.0;
  27. if(reset)
  28. phase = 0.0;
  29. return phase;
  30. }
  31. fun oscillator(pitch, mod) {
  32. mem pre_phase1;
  33. // Implements the resonant filter simulation as shown in
  34. // http://en.wikipedia.org/wiki/Phase_distortion_synthesis
  35. val phase1 = phasor(pitch, false);
  36. val comp = 1.0 - phase1;
  37. val reset = edge((pre_phase1 - phase1) > 0.5);
  38. pre_phase1 = phase1;
  39. val phase2 = phasor(pitch + mod, reset);
  40. val sine = sin(2.0 * pi() * phase2);
  41. return sine * comp;
  42. }
  43. fun lfo(f, gate){
  44. mem phase;
  45. val rate = f * 10.0 * sampletime();
  46. if(edge(gate > 0.0))
  47. phase = 0.0;
  48. phase = phase + rate;
  49. if(phase > 1.0)
  50. phase = phase - 1.0;
  51. return sin(phase * 2.0 * pi()) - 0.5;
  52. }
  53. // Main processing function
  54. fun process(cv, gate){
  55. // LFO
  56. val lfo_rate = getKnob(3);
  57. val lfo_amt = getKnob(4);
  58. val lfo_val = lfo(lfo_rate, gate) * lfo_amt;
  59. // Oscillator
  60. val pitch = getKnob(1) + 10.0 * cv - 2.0;
  61. val mod = getKnob(2) * 2.0 + lfo_val;
  62. val o = oscillator(pitch, mod);
  63. // Envelope
  64. val e = env(gate);
  65. return o * e;
  66. }
  67. and update() {
  68. _ = display("IN1: CV, IN2: GATE");
  69. }