Audio plugin host https://kx.studio/carla
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.

244 lines
5.4KB

  1. /*
  2. * Segment Synthesizer Design
  3. * Implemented by Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz .
  4. *
  5. * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz
  6. */
  7. #ifndef SYNTH_HXX_INCLUDED
  8. #define SYNTH_HXX_INCLUDED
  9. #include <cmath>
  10. #include <cstdlib>
  11. class CSynth
  12. {
  13. public:
  14. CSynth()
  15. {
  16. waveBlend = 0;
  17. freq = 0;
  18. phaseAccum = 0;
  19. playing = false;
  20. cycleSize = 0;
  21. sampleRate = 0;
  22. notePlaying = 0;
  23. env = 0;
  24. envPhase = 0;
  25. aCoeff=dCoeff=rCoeff=0;
  26. stereo = 0;
  27. shape = 0.5;
  28. sustain=release=0.5f;
  29. attack=0.1f;
  30. sustain=0.0f;
  31. mAmp = 0.5;
  32. freqOffset = 0;
  33. waves[0] = 0;
  34. waves[1] = 0;
  35. srand (static_cast <unsigned> (time(0)));
  36. }
  37. float getSinePhase(float x) {
  38. return -(std::sin(x));
  39. }
  40. float getSawPhase(float x) {
  41. return (-(2/M_PI *std::atan(1/std::tan(x/2))));
  42. }
  43. float getRevSawPhase(float x) {
  44. return ((2/M_PI *std::atan(1/std::tan(x/2))));
  45. }
  46. float getSquarePhase(float x) {
  47. return (std::round((std::sin(x)+1)/2)-0.5)*2;
  48. }
  49. //saw, sqr, sin, revSaw
  50. float getBlendedPhase(float x, float wave)
  51. {
  52. //wave = 2;
  53. if (wave>=1 && wave<2) {
  54. /* saw vs sqr */
  55. waveBlend = wave-1;
  56. return (getSawPhase(x)*(1-waveBlend) + getSquarePhase(x)*waveBlend);
  57. } else if (wave>=2 && wave<3) {
  58. /* sqr vs sin */
  59. waveBlend = wave-2;
  60. return (getSquarePhase(x)*(1-waveBlend) + getSinePhase(x)*waveBlend);
  61. } else if (wave>=3 && wave<=4) {
  62. /* sin vs revSaw */
  63. waveBlend = wave-3;
  64. return (getSinePhase(x)*(1-waveBlend) + getRevSawPhase(x)*waveBlend);
  65. } else {
  66. return 0.0f;
  67. }
  68. }
  69. void setWave(int n, float nWave) {
  70. waves[n] = nWave;
  71. }
  72. void setStereo(float nStereo) {
  73. stereo = nStereo;
  74. if (playing) {
  75. freq = 440.0 * pow(2.0, (notePlaying - 69)/12);
  76. freq += freq*(stereo/12);
  77. }
  78. }
  79. float getRandom() {
  80. return static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
  81. }
  82. void setSustain(float nSustain) {
  83. sustain = nSustain*4;
  84. }
  85. void setDecay(float nDecay) {
  86. decay = nDecay*sampleRate;
  87. }
  88. void setRelease(float nRelease) {
  89. release = nRelease*sampleRate/4;
  90. }
  91. void setShape(float nShape) {
  92. shape = nShape;
  93. }
  94. void setMix(float nMix) {
  95. mix = nMix;
  96. }
  97. void setCut(float nCut) {
  98. cut = nCut;
  99. }
  100. void setReso(float nReso) {
  101. reso = nReso;
  102. }
  103. float getWave(int i) {
  104. return waves[i];
  105. }
  106. void stop(int note) {
  107. if (note==notePlaying) {
  108. envPhase = 2; //release
  109. }
  110. }
  111. void play(float note) {
  112. notePlaying = note;
  113. freq = 440.0 * pow(2.0, (notePlaying - 69)/12);
  114. freq += freq*(freqOffset);
  115. freq += freq*(stereo/12);
  116. cycleSize = sampleRate/(freq/4);
  117. playing = true;
  118. phaseAccum = getRandom()*cycleSize;
  119. //phaseAccum = 0;
  120. env = 0.0f;
  121. envPhase = 0;
  122. //env init
  123. decay = 1*sampleRate;
  124. aCoeff = 1.0f - expf(-1/attack*16);
  125. dCoeff = 1.0f - expf(-1/(decay/8));
  126. rCoeff = 1.0f - expf(-1/(release));
  127. }
  128. float run() {
  129. float out = 0;
  130. if (playing) {
  131. out = getSinePhase((phaseAccum/cycleSize)*(2*M_PI))*0.5;
  132. //out += getSinePhase((phaseAccum/cycleSize)*2*(2*M_PI))*amps[0]*0.5;
  133. //out = getSinePhase((phaseAccum/cycleSize)*2*M_PI);
  134. //printf("out: %f\n", (waves[0]*3));
  135. //printf("out: %f\n", phaseAccum);
  136. out += getBlendedPhase((phaseAccum/cycleSize)*2*M_PI, (waves[0]*3)+1);
  137. out += getBlendedPhase((phaseAccum/cycleSize)*4*M_PI, (waves[0]*3)+1)*(sustain/4);
  138. out += getBlendedPhase((phaseAccum/cycleSize)*8*M_PI, (waves[0]*3)+1)*(sustain/4);
  139. out += getBlendedPhase((phaseAccum/cycleSize)*16*M_PI, (waves[0]*3)+1)*(sustain/4)/2;
  140. out += getBlendedPhase((phaseAccum/cycleSize)*6*M_PI, (waves[0]*3)+1)*shape;
  141. out += getBlendedPhase((phaseAccum/cycleSize)*12*M_PI, (waves[0]*3)+1)*(1-shape)/2;
  142. out += getBlendedPhase((phaseAccum/cycleSize)*3*M_PI, (waves[0]*3)+1)*(1-mix);
  143. out += getBlendedPhase((phaseAccum/cycleSize)*4*M_PI, (waves[1]*3)+1);
  144. out += getBlendedPhase((phaseAccum/cycleSize)*2*M_PI*(getBlendedPhase((phaseAccum/cycleSize)*M_PI, (waves[1]*3)+1)), (waves[1]*3)+1)*mix;
  145. //printf("out: %f\n", waves[0]*4);
  146. //std::cout << (waves[0]*3)+1 << std::endl;
  147. phaseAccum++;
  148. if (phaseAccum>cycleSize) {
  149. phaseAccum = 0;
  150. }
  151. //calculate amplitude envelope
  152. if (envPhase==0) {
  153. //attack phase
  154. env+=aCoeff * ((1.0/0.63) - env);
  155. if (env>1.0) envPhase+=2;
  156. } else if (envPhase==1) {
  157. //decay and sustain phase
  158. env+=dCoeff * (sustain/4 - env);
  159. } else {
  160. //release phase
  161. env += rCoeff * (1.0-(1.0/0.63) - env);
  162. if (env<0.0) { playing = false; env = 0.0; }
  163. }
  164. //apply amplitude envelope
  165. out*=env;
  166. //apply master volume
  167. //out*=mAmp*0.5;
  168. //apply hard clipping
  169. //if (out>1) out=1;
  170. //if (out<-1) out=-1;
  171. if (out!=0) {
  172. //printf("out: %f\n", out);
  173. }
  174. }
  175. return out;
  176. }
  177. void setSampleRate(float sr) {
  178. sampleRate = sr;
  179. attack = sampleRate/2;
  180. decay = sampleRate/2;
  181. release = sampleRate/2;
  182. }
  183. private:
  184. /* vcf filter */
  185. float waves[2];
  186. float waveBlend;
  187. float freq;
  188. float freqOffset;
  189. float stereo;
  190. float mAmp;
  191. float phaseAccum;
  192. float cycleSize;
  193. float sampleRate;
  194. float notePlaying;
  195. bool playing;
  196. float mix;
  197. float reso;
  198. float cut;
  199. float shape;
  200. float attack, decay, sustain, release;
  201. float env;
  202. float envPhase; //0, 1(d+s), 2
  203. float aCoeff, dCoeff, rCoeff, gCoeff;
  204. };
  205. #endif // SYNTH_HXX_INCLUDED