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.

415 lines
13KB

  1. /* nekobee DSSI software synthesizer plugin
  2. */
  3. #define _BSD_SOURCE 1
  4. #define _SVID_SOURCE 1
  5. #define _ISOC99_SOURCE 1
  6. #include <math.h>
  7. #include "nekobee.h"
  8. #include "nekobee_synth.h"
  9. #include "nekobee_voice.h"
  10. #ifndef M_PI
  11. #define M_PI 3.14159265358979323846
  12. #endif
  13. #define M_2PI_F (2.0f * (float)M_PI)
  14. #define M_PI_F (float)M_PI
  15. #define VCF_FREQ_MAX (0.825f) /* original filters only stable to this frequency */
  16. static int tables_initialized = 0;
  17. float nekobee_pitch[128];
  18. #define pitch_ref_note 69
  19. #define volume_to_amplitude_scale 128
  20. static float volume_to_amplitude_table[4 + volume_to_amplitude_scale + 2];
  21. static float velocity_to_attenuation[128];
  22. static float qdB_to_amplitude_table[4 + 256 + 0];
  23. void
  24. nekobee_init_tables(void)
  25. {
  26. int i;
  27. float pexp;
  28. float volume, volume_exponent;
  29. float ol, amp;
  30. if (tables_initialized)
  31. return;
  32. /* MIDI note to pitch */
  33. for (i = 0; i < 128; ++i) {
  34. pexp = (float)(i - pitch_ref_note) / 12.0f;
  35. nekobee_pitch[i] = powf(2.0f, pexp);
  36. }
  37. /* volume to amplitude
  38. *
  39. * This generates a curve which is:
  40. * volume_to_amplitude_table[128 + 4] = 0.25 * 3.16... ~= -2dB
  41. * volume_to_amplitude_table[64 + 4] = 0.25 * 1.0 ~= -12dB
  42. * volume_to_amplitude_table[32 + 4] = 0.25 * 0.316... ~= -22dB
  43. * volume_to_amplitude_table[16 + 4] = 0.25 * 0.1 ~= -32dB
  44. * etc.
  45. */
  46. volume_exponent = 1.0f / (2.0f * log10f(2.0f));
  47. for (i = 0; i <= volume_to_amplitude_scale; i++) {
  48. volume = (float)i / (float)volume_to_amplitude_scale;
  49. volume_to_amplitude_table[i + 4] = powf(2.0f * volume, volume_exponent) / 4.0f;
  50. }
  51. volume_to_amplitude_table[ -1 + 4] = 0.0f;
  52. volume_to_amplitude_table[129 + 4] = volume_to_amplitude_table[128 + 4];
  53. /* velocity to attenuation
  54. *
  55. * Creates the velocity to attenuation lookup table, for converting
  56. * velocities [1, 127] to full-velocity-sensitivity attenuation in
  57. * quarter decibels. Modeled after my TX-7's velocity response.*/
  58. velocity_to_attenuation[0] = 253.9999f;
  59. for (i = 1; i < 127; i++) {
  60. if (i >= 10) {
  61. ol = (powf(((float)i / 127.0f), 0.32f) - 1.0f) * 100.0f;
  62. amp = powf(2.0f, ol / 8.0f);
  63. } else {
  64. ol = (powf(((float)10 / 127.0f), 0.32f) - 1.0f) * 100.0f;
  65. amp = powf(2.0f, ol / 8.0f) * (float)i / 10.0f;
  66. }
  67. velocity_to_attenuation[i] = log10f(amp) * -80.0f;
  68. }
  69. velocity_to_attenuation[127] = 0.0f;
  70. /* quarter-decibel attenuation to amplitude */
  71. qdB_to_amplitude_table[-1 + 4] = 1.0f;
  72. for (i = 0; i <= 255; i++) {
  73. qdB_to_amplitude_table[i + 4] = powf(10.0f, (float)i / -80.0f);
  74. }
  75. tables_initialized = 1;
  76. }
  77. static inline float
  78. volume(float level)
  79. {
  80. unsigned char segment;
  81. float fract;
  82. level *= (float)volume_to_amplitude_scale;
  83. segment = lrintf(level - 0.5f);
  84. fract = level - (float)segment;
  85. return volume_to_amplitude_table[segment + 4] + fract *
  86. (volume_to_amplitude_table[segment + 5] -
  87. volume_to_amplitude_table[segment + 4]);
  88. }
  89. static inline float
  90. qdB_to_amplitude(float qdB)
  91. {
  92. int i = lrintf(qdB - 0.5f);
  93. float f = qdB - (float)i;
  94. return qdB_to_amplitude_table[i + 4] + f *
  95. (qdB_to_amplitude_table[i + 5] -
  96. qdB_to_amplitude_table[i + 4]);
  97. }
  98. void blosc_place_step_dd(float *buffer, int index, float phase, float w, float scale){
  99. float r;
  100. int i;
  101. r = MINBLEP_PHASES * phase / w;
  102. i = lrintf(r - 0.5f);
  103. r -= (float)i;
  104. i &= MINBLEP_PHASE_MASK; /* port changes can cause i to be out-of-range */
  105. /* This would be better than the above, but more expensive:
  106. * while (i < 0) {
  107. * i += MINBLEP_PHASES;
  108. * index++;
  109. * }
  110. */
  111. while (i < MINBLEP_PHASES * STEP_DD_PULSE_LENGTH) {
  112. buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta);
  113. i += MINBLEP_PHASES;
  114. index++;
  115. }
  116. }
  117. void vco(unsigned long sample_count, nekobee_voice_t *voice, struct blosc *osc,
  118. int index, float w)
  119. {
  120. unsigned long sample;
  121. float pos = osc->pos;
  122. float pw, gain, halfgain, out;
  123. pw=0.46f;
  124. gain=1.0f;
  125. halfgain=gain*0.5f;
  126. int bp_high = osc->bp_high;
  127. out=(bp_high ? halfgain : -halfgain);
  128. switch (osc->waveform)
  129. {
  130. default:
  131. case 0: {
  132. for (sample = 0; sample < sample_count; sample++) {
  133. pos += w;
  134. if (bp_high) {
  135. if (pos >= pw) {
  136. blosc_place_step_dd(voice->osc_audio, index, pos - pw, w, -gain);
  137. bp_high = 0;
  138. out = -halfgain;
  139. }
  140. if (pos >= 1.0f) {
  141. pos -= 1.0f;
  142. blosc_place_step_dd(voice->osc_audio, index, pos, w, gain);
  143. bp_high = 1;
  144. out = halfgain;
  145. }
  146. } else {
  147. if (pos >= 1.0f) {
  148. pos -= 1.0f;
  149. blosc_place_step_dd(voice->osc_audio, index, pos, w, gain);
  150. bp_high = 1;
  151. out = halfgain;
  152. }
  153. if (bp_high && pos >= pw) {
  154. blosc_place_step_dd(voice->osc_audio, index, pos - pw, w, -gain);
  155. bp_high = 0;
  156. out = -halfgain;
  157. }
  158. }
  159. voice->osc_audio[index + DD_SAMPLE_DELAY] += out;
  160. index++;
  161. }
  162. osc->pos = pos;
  163. osc->bp_high = bp_high;
  164. break;
  165. }
  166. case 1: // sawtooth wave
  167. {
  168. for (sample=0; sample < sample_count; sample++) {
  169. pos += w;
  170. if (pos >= 1.0f) {
  171. pos -= 1.0f;
  172. blosc_place_step_dd(voice->osc_audio, index, pos, w, gain);
  173. }
  174. voice->osc_audio[index + DD_SAMPLE_DELAY] += gain * (0.5f - pos);
  175. index++;
  176. }
  177. break;
  178. }
  179. }
  180. osc->pos=pos;
  181. }
  182. static inline void
  183. vcf_4pole(nekobee_voice_t *voice, unsigned long sample_count,
  184. float *in, float *out, float *cutoff, float qres, float *amp)
  185. {
  186. unsigned long sample;
  187. float freqcut, freqcut2, highpass,
  188. delay1 = voice->delay1,
  189. delay2 = voice->delay2,
  190. delay3 = voice->delay3,
  191. delay4 = voice->delay4;
  192. qres = 2.0f - qres * 1.995f;
  193. for (sample = 0; sample < sample_count; sample++) {
  194. /* Hal Chamberlin's state variable filter */
  195. freqcut = cutoff[sample] * 2.0f;
  196. freqcut2 = cutoff[sample] * 4.0f;
  197. if (freqcut > VCF_FREQ_MAX) freqcut = VCF_FREQ_MAX;
  198. if (freqcut2 > VCF_FREQ_MAX) freqcut2 = VCF_FREQ_MAX;
  199. delay2 = delay2 + freqcut * delay1; /* delay2/4 = lowpass output */
  200. highpass = in[sample] - delay2 - qres * delay1;
  201. delay1 = freqcut * highpass + delay1; /* delay1/3 = bandpass output */
  202. delay4 = delay4 + freqcut2 * delay3;
  203. highpass = delay2 - delay4 - qres * delay3;
  204. delay3 = freqcut2 * highpass + delay3;
  205. /* mix filter output into output buffer */
  206. out[sample] += 0.1*atan(3*delay4 * amp[sample]);
  207. }
  208. voice->delay1 = delay1;
  209. voice->delay2 = delay2;
  210. voice->delay3 = delay3;
  211. voice->delay4 = delay4;
  212. voice->c5 = 0.0f;
  213. }
  214. /*
  215. * nekobee_voice_render
  216. *
  217. * generate the actual sound data for this voice
  218. */
  219. void
  220. nekobee_voice_render(nekobee_synth_t *synth, nekobee_voice_t *voice,
  221. float *out, unsigned long sample_count,
  222. int do_control_update)
  223. {
  224. unsigned long sample;
  225. /* state variables saved in voice */
  226. float lfo_pos = voice->lfo_pos,
  227. vca_eg = voice->vca_eg,
  228. vcf_eg = voice->vcf_eg;
  229. unsigned char vca_eg_phase = voice->vca_eg_phase,
  230. vcf_eg_phase = voice->vcf_eg_phase;
  231. int osc_index = voice->osc_index;
  232. /* temporary variables used in calculating voice */
  233. float fund_pitch;
  234. float deltat = synth->deltat;
  235. float freq, cutoff, vcf_amt;
  236. float vcf_acc_amt;
  237. /* set up synthesis variables from patch */
  238. float omega;
  239. float vca_eg_amp = qdB_to_amplitude(velocity_to_attenuation[voice->velocity] * 0);
  240. float vca_eg_rate_level[3], vca_eg_one_rate[3];
  241. float vcf_eg_amp = qdB_to_amplitude(velocity_to_attenuation[voice->velocity] * 0);
  242. float vcf_eg_rate_level[3], vcf_eg_one_rate[3];
  243. float qres = synth->resonance;
  244. float vol_out = volume(synth->volume);
  245. float velocity = (voice->velocity);
  246. float vcf_egdecay = synth->decay;
  247. fund_pitch = 0.1f*voice->target_pitch +0.9 * voice->prev_pitch; /* glide */
  248. if (do_control_update) {
  249. voice->prev_pitch = fund_pitch; /* save pitch for next time */
  250. }
  251. fund_pitch *= 440.0f;
  252. omega = synth->tuning * fund_pitch;
  253. // if we have triggered ACCENT
  254. // we need a shorter decay
  255. // we should probably have something like this in the note on code
  256. // that could trigger an ACCENT light
  257. if (velocity>90) {
  258. vcf_egdecay=.0005;
  259. }
  260. // VCA - In a real 303, it is set for around 2 seconds
  261. vca_eg_rate_level[0] = 0.1f * vca_eg_amp; // instant on attack
  262. vca_eg_one_rate[0] = 0.9f; // very fast
  263. vca_eg_rate_level[1] = 0.0f; // sustain is zero
  264. vca_eg_one_rate[1] = 1.0f - 0.00001f; // decay time is very slow
  265. vca_eg_rate_level[2] = 0.0f; // decays to zero
  266. vca_eg_one_rate[2] = 0.975f; // very fast release
  267. // VCF - funny things go on with the accent
  268. vcf_eg_rate_level[0] = 0.1f * vcf_eg_amp;
  269. vcf_eg_one_rate[0] = 1-0.1f; //0.9f;
  270. vcf_eg_rate_level[1] = 0.0f; // vcf_egdecay * *(synth->vcf_eg_sustain_level) * vcf_eg_amp;
  271. vcf_eg_one_rate[1] = 1.0f - vcf_egdecay;
  272. vcf_eg_rate_level[2] = 0.0f;
  273. vcf_eg_one_rate[2] = 0.9995f; // 1.0f - *(synth->vcf_eg_release_time);
  274. vca_eg_amp *= 0.99f;
  275. vcf_eg_amp *= 0.99f;
  276. freq = M_PI_F * deltat * fund_pitch * synth->mod_wheel; /* now (0 to 1) * pi */
  277. cutoff = 0.008f * synth->cutoff;
  278. // 303 always has slight VCF mod
  279. vcf_amt = 0.05f+(synth->envmod*0.75);
  280. /* copy some things so oscillator functions can see them */
  281. voice->osc1.waveform = lrintf(synth->waveform);
  282. // work out how much the accent will affect the filter
  283. vcf_acc_amt=.333f+ (synth->resonance/1.5f);
  284. for (sample = 0; sample < sample_count; sample++) {
  285. vca_eg = vca_eg_rate_level[vca_eg_phase] + vca_eg_one_rate[vca_eg_phase] * vca_eg;
  286. vcf_eg = vcf_eg_rate_level[vcf_eg_phase] + vcf_eg_one_rate[vcf_eg_phase] * vcf_eg;
  287. voice->freqcut_buf[sample] = (cutoff + (vcf_amt * vcf_eg/2.0f) + (synth->vcf_accent * synth->accent*0.5f));
  288. voice->vca_buf[sample] = vca_eg * vol_out*(1.0f + synth->accent*synth->vca_accent);
  289. if (!vca_eg_phase && vca_eg > vca_eg_amp) vca_eg_phase = 1; /* flip from attack to decay */
  290. if (!vcf_eg_phase && vcf_eg > vcf_eg_amp) vcf_eg_phase = 1; /* flip from attack to decay */
  291. }
  292. // oscillator
  293. vco(sample_count, voice, &voice->osc1, osc_index, deltat * omega);
  294. // VCF and VCA
  295. vcf_4pole(voice, sample_count, voice->osc_audio + osc_index, out, voice->freqcut_buf, qres, voice->vca_buf);
  296. osc_index += sample_count;
  297. if (do_control_update) {
  298. /* do those things should be done only once per control-calculation
  299. * interval ("nugget"), such as voice check-for-dead, pitch envelope
  300. * calculations, volume envelope phase transition checks, etc. */
  301. /* check if we've decayed to nothing, turn off voice if so */
  302. if (vca_eg_phase == 2 && voice->vca_buf[sample_count - 1] < 6.26e-6f) {
  303. // sound has completed its release phase (>96dB below volume '5' max)
  304. XDB_MESSAGE(XDB_NOTE, " nekobee_voice_render check for dead: killing note id %d\n", voice->note_id);
  305. nekobee_voice_off(voice);
  306. return; // we're dead now, so return
  307. }
  308. /* already saved prev_pitch above */
  309. /* check oscillator audio buffer index, shift buffer if necessary */
  310. if (osc_index > MINBLEP_BUFFER_LENGTH - (XSYNTH_NUGGET_SIZE + LONGEST_DD_PULSE_LENGTH)) {
  311. memcpy(voice->osc_audio, voice->osc_audio + osc_index,
  312. LONGEST_DD_PULSE_LENGTH * sizeof (float));
  313. memset(voice->osc_audio + LONGEST_DD_PULSE_LENGTH, 0,
  314. (MINBLEP_BUFFER_LENGTH - LONGEST_DD_PULSE_LENGTH) * sizeof (float));
  315. osc_index = 0;
  316. }
  317. }
  318. /* save things for next time around */
  319. voice->lfo_pos = lfo_pos;
  320. voice->vca_eg = vca_eg;
  321. voice->vca_eg_phase = vca_eg_phase;
  322. voice->vcf_eg = vcf_eg;
  323. voice->vcf_eg_phase = vcf_eg_phase;
  324. voice->osc_index = osc_index;
  325. return;
  326. (void)freq;
  327. (void)vcf_acc_amt;
  328. }