// License: GPL - http://www.gnu.org/licenses/gpl.html

desc:Drum Generator

import Tale/midi_queue.jsfx-inc
import Nz0/inc/ad.jsfx-inc
import Nz0/inc/dsf_oscillator.jsfx-inc

slider1:36<0,129,1{0: C-1,1: C#-1,2: D-1,3: D#-1,4: E-1,5: F-1,6: F#-1,7: G-1,8: G#-1,9: A-1,10: Bb-1,11: B-1,12: C0,13: C#0,14: D0,15: D#0,16: E0,17: F0,18: F#0,19: G0,20: G#0,21: A0,22: Bb0,23: B0,24: C1,25: C#1,26: D1,27: D#1,28: E1,29: F1,30: F#1,31: G1,32: G#1,33: A1,34: Bb1,35: B1,36: C2,37: C#2,38: D2,39: D#2,40: E2,41: F2,42: F#2,43: G2,44: G#2,45: A2,46: Bb2,47: B2,48: C3,49: C#3,50: D3,51: D#3,52: E3,53: F3,54: F#3,55: G3,56: G#3,57: A3,58: Bb3,59: B3,60: C4,61: C#4,62: D4,63: D#4,64: E4,65: F4,66: F#4,67: G4,68: G#4,69: A4,70: Bb4,71: B4,72: C5,73: C#5,74: D5,75: D#5,76: E5,77: F5,78: F#5,79: G5,80: G#5,81: A5,82: Bb5,83: B5,84: C6,85: C#6,86: D6,87: D#6,88: E6,89: F6,90: F#6,91: G6,92: G#6,93: A6,94: Bb6,95: B6,96: C7,97: C#7,98: D7,99: D#7,100: E7,101: F7,102: F#7,103: G7,104: G#7,105: A7,106: Bb7,107: B7,108: C8,109: C#8,110: D8,111: D#8,112: E8,113: F8,114: F#8,115: G8,116: G#8,117: A8,118: Bb8,119: B8,120: C9,121: C#9,122: D9,123: D#9,124: E9,125: F9,126: F#9,127: G9}>Midi Key Filter
slider2:80<20,20000,0.01>Osc Freq (Hz)
slider3:50<1,5000,0.01>Partial Freq (Hz)
slider4:3<1,100,1>Number of Partials
slider5:0.35<0.00,4,0.01>Partial Amplitude
slider6:25<0,5000,1>Amplitude Attack (ms)
slider7:221<0,5000,1>Amplitude Decay (ms)
slider8:-24<-48,48,1>Pitch (semitones)
slider9:0<0,5000,1>Pitch Attack
slider10:50<0,5000,1>Pitch Decay
slider11:1<0,3,1{None,Arraya,Sigmoid,Atan}>Waveshaper
slider12:1<1,20,0.01>K
slider13:0<0,1,,1{Mono,Stereo}>M/S
slider14:-6<-120,0,1>Osc Gain (dB)


@init


function waveshaper(x,shape_type,k)
(
	shape_type == 0 ? x:
	shape_type == 1 ? 1.5 * x *(1 - x * x / 3):
	shape_type == 2 ? 2/(1 + exp(-k * x)) - 1 :
	atan(k * x)/atan(k);
);


max_freq = 20000;

//init oscillator AD
amp_osc.ad_init();

//init pitch AD
pitch.ad_init();

//init DSF Oscillator
dsf.DSF_init();

@slider

//Partial amplitude cannot be 1
slider5 == 1 ? ( slider5 = 1.000001; slider_automate(slider););

//Highest Partial should be less than max_freq else reset parameters
note_max_freq =  slider2 + slider3 * slider4;
note_max_freq > max_freq ? (
	slider2 = 120;
	slider3 = 100;
	slider4 = 4;
	slider5 = 0.9;
	sliderindex = 2;
	loop(4,sliderindex += 1; slider_automate(2 ^ sliderindex););
);

midi_note_filter = slider1;
base_freq = slider2 / srate;
part_freq = slider3;
n_part = slider4;
amp_part = slider5;

amp_osc.ad_chg_parameters(slider6,slider7);

pitch_sem = slider8;
pitch.ad_chg_parameters(slider9,slider10);

shape_type = slider11;
shape_k = slider12;

ms = slider13;

osc_gain = 10^(0.05 * slider14);


start_freq = base_freq * 2^(-pitch_sem/12);
pitch_range = start_freq-base_freq;


dsf.DSF_setdtc(base_freq); 
dsf.DSF_setfm(part_freq);
dsf.DSF_set_amp(amp_part,n_part);

@block
midiq.midiq_collect();

//rescale oscillator - not mandatory if init at note_on
//dsf.DSF_rescale();


@sample

while(midiq.midiq_remove()) (
  
  status = midiq.msg1 & 0xF0;
  velocity = midiq.msg3;

  // Note On
  status == 0x90 && velocity &&  midi_note_filter == midiq.msg2 ? (
    
    note = midiq.msg2;
   
   //reset oscillator
   dsf.DSF_init();
   
   amp_osc.ad_a(velocity/127);
   pitch.ad_a(1);
    
  )
  
);


//Calculate DSF Output
dsf.DSF_calc();

//process ADs
amp_osc.ad_process();
pitch.ad_process();

dsf.DSF_setdtc(base_freq + pitch_range * pitch.env);


ms == 0 ?
(
	out_wave = 0.5 * osc_gain * waveshaper(dsf.right * amp_osc.env,shape_type,shape_k);

	spl0 += out_wave;
	spl1 += out_wave;
):
(
	spl0 +=osc_gain * waveshaper(dsf.left * amp_osc.env,shape_type,shape_k);
	spl1 +=osc_gain * waveshaper(dsf.right * amp_osc.env,shape_type,shape_k);
);

//increment DSF oscillator
dsf.DSF_inc();
