Browse Source

add lfo, pitch bend, key stack (for unison trills), filter lfo, filter EG intensity, 24db/oct filter

vampirefrog 3 years ago
parent
commit
693332aa07
12 changed files with 300 additions and 92 deletions
  1. 4
    3
      Makefile
  2. 50
    8
      filter.c
  3. 10
    4
      filter.h
  4. 31
    24
      main.c
  5. 5
    0
      oscillator.c
  6. 1
    1
      oscillator.h
  7. 19
    0
      sineosc.c
  8. 12
    0
      sineosc.h
  9. 139
    48
      synth.c
  10. 20
    1
      synth.h
  11. 4
    3
      voice.c
  12. 5
    0
      voice.h

+ 4
- 3
Makefile View File

@@ -1,10 +1,11 @@
1
-CFLAGS=$(shell pkg-config alsa jack --cflags)
2
-LDFLAGS=$(shell pkg-config alsa jack --libs)
1
+PKGS=alsa jack gtk+-3.0
2
+CFLAGS=$(shell pkg-config $(PKGS) --cflags)
3
+LDFLAGS=$(shell pkg-config $(PKGS) --libs)
3 4
 ifeq ($(DEBUG),true)
4 5
 CFLAGS+=-Wall -g
5 6
 endif
6 7
 
7 8
 programs=vampisynth
8
-vampisynth_SRCS=synth.c envelope.c filter.c oscillator.c voice.c main.c
9
+vampisynth_SRCS=synth.c envelope.c filter.c oscillator.c voice.c sineosc.c main.c
9 10
 
10 11
 include common.mk/common.mk

+ 50
- 8
filter.c View File

@@ -1,30 +1,72 @@
1 1
 #include <math.h>
2
+#include <string.h>
3
+#include <stdlib.h>
2 4
 
3 5
 #include "filter.h"
4 6
 
5 7
 void filter_init(struct Filter *filter, float cutoff, float resonance) {
6
-	filter->v0 = filter->v1 = 0;
8
+	memset(filter, 0, sizeof(struct Filter));
7 9
 	filter->cutoff = cutoff;
8 10
 	filter->resonance = resonance;
9 11
 }
10 12
 
11 13
 void filter_set_cutoff(struct Filter *filter, float cutoff) {
12 14
 	filter->cutoff = cutoff;
15
+	if(filter->cutoff > 0.9) filter->cutoff = 0.9;
16
+	else if(filter->cutoff < 0.0) filter->cutoff = 0.0;
13 17
 }
14 18
 
15 19
 void filter_set_resonance(struct Filter *filter, float resonance) {
16 20
 	filter->resonance = resonance;
17 21
 }
18 22
 
23
+// http://www.musicdsp.org/showone.php?id=25
24
+// float filter_sample(struct Filter *filter, float input) {
25
+// 	float q = 1.0f - filter->cutoff;
26
+// 	float p = filter->cutoff + 0.8f * filter->cutoff * q;
27
+// 	float f = p + p - 1.0f;
28
+// 	q = filter->resonance * (1.0f + 0.5f * q * (1.0f - q + 5.6f * q * q));
29
+
30
+// #define OVERSAMPLE 2
31
+// 	float output = 0;
32
+// 	for(int i = 0; i < OVERSAMPLE; i++) {
33
+// 		input -= q * filter->b4;                          //feedback
34
+// 		float t1 = filter->b1;  filter->b1 = (input + filter->b0) * p - filter->b1 * f;
35
+// 		float t2 = filter->b2;  filter->b2 = (filter->b1 + t1) * p - filter->b2 * f;
36
+// 		t1 = filter->b3;  filter->b3 = (filter->b2 + t2) * p - filter->b3 * f;
37
+// 		filter->b4 = (filter->b3 + t1) * p - filter->b4 * f;
38
+// 		filter->b4 = filter->b4 - filter->b4 * filter->b4 * filter->b4 * 0.166667f;    //clipping
39
+// 		filter->b0 = input;
40
+// 		output += filter->b4;
41
+// 	}
42
+// 	return output / (float)OVERSAMPLE;
43
+// }
44
+
45
+// mad's filter code
19 46
 float filter_sample(struct Filter *filter, float input) {
20
-	float c = pow(0.5, (128-filter->cutoff)   / 16.0);
21
-	float r = pow(0.5, (filter->resonance+24) / 16.0);
47
+	if(++filter->last_calc >= 16) {
48
+		filter->last_calc = 0;
49
+		filter->cutoff_calc = pow (0.5, 8.5 - (filter->cutoff)*8  );
50
+		filter->resonance_calc = filter->resonance;
51
+	}
52
+	float cutoff = filter->cutoff_calc;
53
+	float resonance = filter->resonance_calc;
22 54
 
23
-	float outputs[2]; // oversample
24
-	for(int i = 0; i < 2; i++) {
25
-		filter->v0 =  (1-r*c)*filter->v0  -  (c)*filter->v1  + (c)*input;
26
-		outputs[i] = filter->v1 = (1-r*c)*filter->v1  +  (c)*filter->v0;
55
+#define OVERSAMPLE 2
56
+	float output = 0;
57
+	for(int i = 0; i < OVERSAMPLE; i++) {
58
+		float in = filter->resonance_input;
59
+		if(in > 1) in = 1;
60
+		if(in < -1) in = -1;
61
+		in = 1.5*in - 0.5*in*in*in;
62
+		in = input - in;
63
+		filter->stage_1 += (in - filter->stage_1) * cutoff;
64
+		filter->stage_2 += (filter->stage_1 - filter->stage_2) * cutoff;
65
+		filter->stage_3 += (filter->stage_2 - filter->stage_3) * cutoff;
66
+		filter->stage_4 += (filter->stage_3 - filter->stage_4) * cutoff;
67
+		output += filter->stage_4;
68
+		filter->resonance_input = output * resonance;
27 69
 	}
28 70
 
29
-	return (outputs[0] + outputs[1]) / 2;
71
+	return output / OVERSAMPLE;
30 72
 }

+ 10
- 4
filter.h View File

@@ -2,13 +2,19 @@
2 2
 #define FILTER_H_
3 3
 
4 4
 struct Filter {
5
-	float v0, v1;
5
+	// public
6 6
 	float cutoff, resonance;
7
+
8
+	// private
9
+	float resonance_input, stage_1, stage_2, stage_3, stage_4;
10
+	float cutoff_calc, resonance_calc;
11
+	int last_calc;
12
+
13
+	float b0, b1, b2, b3, b4;  //filter buffers (beware denormals!)
7 14
 };
8 15
 void filter_init(struct Filter *filter, float cutoff, float q);
9
-void filter_set_cutoff(struct Filter *filter, float cutoff); // frequency in Hz
10
-void filter_set_resonance(struct Filter *filter, float q);
11
-void filter_set_cutoff_and_resonance(struct Filter *filter, float cutoff, float q); // both
16
+void filter_set_cutoff(struct Filter *filter, float cutoff);
17
+void filter_set_resonance(struct Filter *filter, float resonance);
12 18
 float filter_sample(struct Filter *filter, float input);
13 19
 
14 20
 #endif /* FILTER_H_ */

+ 31
- 24
main.c View File

@@ -42,7 +42,7 @@ int process (jack_nframes_t nframes, void *arg) {
42 42
 	buffers[0] = (sample_t *) jack_port_get_buffer (output_ports[0], nframes);
43 43
 	buffers[1] = (sample_t *) jack_port_get_buffer (output_ports[1], nframes);
44 44
 	for(int i = 0; i < nframes; i++) {
45
-		float out[2];
45
+		float out[2] = {0, 0};
46 46
 		synth_render_sample(&synth, out);
47 47
 		buffers[0][i] = out[0];
48 48
 		buffers[1][i] = out[1];
@@ -154,25 +154,33 @@ void midi_action(snd_seq_t *seq_handle) {
154 154
 					printf("Note off %s (%d) %d\n", midi_note_name(ev->data.note.note), ev->data.note.note, ev->data.note.velocity);
155 155
 				synth_note_off(&synth, ev->data.note.note, ev->data.note.velocity);
156 156
 				break;
157
+			case SND_SEQ_EVENT_PITCHBEND:
158
+				synth_pitch_bend(&synth, ev->data.control.value);
159
+				break;
157 160
 			case SND_SEQ_EVENT_CONTROLLER:
158 161
 				if(verbose)
159 162
 					printf("CC 0x%02x (%s) %d\n", ev->data.control.param, midi_cc_name(ev->data.control.param), ev->data.control.value);
160
-				if(ev->data.control.param == 91) {
163
+				if(ev->data.control.param == 0x01) {
164
+					if(verbose)
165
+						printf("LFO Depth %d\n", ev->data.control.value);
166
+					synth_set_lfo_depth(&synth, ev->data.control.value);
167
+				} else if(ev->data.control.param == 7) {
168
+					if(verbose)
169
+						printf("Volume %d\n", ev->data.control.value);
170
+					synth_set_volume(&synth, ev->data.control.value);
171
+				} else if(ev->data.control.param == 91) {
161 172
 					if(verbose)
162 173
 						printf("Unison spread %d\n", ev->data.control.value);
163 174
 					synth_set_unison_spread(&synth, ev->data.control.value);
164
-				}
165
-				if(ev->data.control.param == 93) {
175
+				} else if(ev->data.control.param == 93) {
166 176
 					if(verbose)
167 177
 						printf("Stereo spread %d\n", ev->data.control.value);
168 178
 					synth_set_stereo_spread(&synth, ev->data.control.value);
169
-				}
170
-				if(ev->data.control.param == 74) {
179
+				} else if(ev->data.control.param == 74) {
171 180
 					if(verbose)
172 181
 						printf("Cutoff %d\n", ev->data.control.value);
173 182
 					synth_set_cutoff_freq(&synth, ev->data.control.value);
174
-				}
175
-				if(ev->data.control.param == 71) {
183
+				} else if(ev->data.control.param == 71) {
176 184
 					if(verbose)
177 185
 						printf("Resonance %d\n", ev->data.control.value);
178 186
 					synth_set_resonance(&synth, ev->data.control.value);
@@ -236,6 +244,21 @@ int main(int argc, char **argv) {
236 244
 
237 245
 	sr = jack_get_sample_rate(client);
238 246
 
247
+	synth_init(&synth);
248
+	synth.osc_env.attack = 2;
249
+	synth.osc_env.decay = 200;
250
+	synth.osc_env.sustain = 100;
251
+	synth.osc_env.release = 100;
252
+	synth.filter_env.attack = 150;
253
+	synth.filter_env.decay = 100;
254
+	synth.filter_env.sustain = 100;
255
+	synth.filter_env.release = 100;
256
+	synth.filter_eg_intensity = .8;
257
+	synth.filter_kbd_track = .5;
258
+	sine_osc_set_freq(&synth.lfo_osc, 6);
259
+	synth.pitch_bend_range = 12; // semitones
260
+//	synth.monophonic = 1;
261
+
239 262
 	if (jack_activate(client)) {
240 263
 		fprintf (stderr, "cannot activate client");
241 264
 		exit (1);
@@ -256,22 +279,6 @@ int main(int argc, char **argv) {
256 279
 		fprintf (stderr, "cannot connect input ports\n");
257 280
 	}
258 281
 
259
-	synth_init(&synth);
260
-	synth.osc_env.attack = 2;
261
-	synth.osc_env.decay = 100;
262
-	synth.osc_env.sustain = 90;
263
-	synth.osc_env.release = 100;
264
-	synth.filter_env.attack = 1000;
265
-	synth.filter_env.decay = 200;
266
-	synth.filter_env.sustain = 90;
267
-	synth.filter_env.release = 100;
268
-	synth.monophonic = 1;
269
-
270
-	if (jack_activate(client)) {
271
-		fprintf (stderr, "cannot activate client");
272
-		return 1;
273
-	}
274
-
275 282
 	snd_seq_t *seq_handle;
276 283
 	int npfd;
277 284
 	struct pollfd *pfd;

+ 5
- 0
oscillator.c View File

@@ -1,4 +1,5 @@
1 1
 #include "oscillator.h"
2
+#include "config.h"
2 3
 
3 4
 int16_t oscillator_render_sample(struct Oscillator *osc) {
4 5
 	if(osc->period == 0) return 0;
@@ -15,3 +16,7 @@ int16_t oscillator_render_sample(struct Oscillator *osc) {
15 16
 
16 17
 	return (1 << 13) - (osc->phase << 3) / (osc->period >> 11) + (osc->sub_phase - osc->period / 2 > osc->period ? 4096 : -4096);
17 18
 }
19
+
20
+void oscillator_set_freq(struct Oscillator *osc, float freq) {
21
+	osc->period = ((float)SAMPLE_RATE / freq) * 65536.0;
22
+}

+ 1
- 1
oscillator.h View File

@@ -18,6 +18,6 @@ struct Oscillator {
18 18
 };
19 19
 
20 20
 int16_t oscillator_render_sample(struct Oscillator *osc);
21
-void oscillator_set_freq(fixed freq); // fixed 16.16
21
+void oscillator_set_freq(struct Oscillator *osc, float freq); // fixed 16.16
22 22
 
23 23
 #endif /* OSCILLATOR_H_ */

+ 19
- 0
sineosc.c View File

@@ -0,0 +1,19 @@
1
+#include <math.h>
2
+
3
+#include "sineosc.h"
4
+#include "config.h"
5
+
6
+void sine_osc_init(struct SineOsc *osc) {
7
+	osc->s0 = 1.0;
8
+	osc->s1 = 0.0;
9
+}
10
+
11
+void sine_osc_set_freq(struct SineOsc *osc, float freq) {
12
+	osc->a = 2.0 * sinf(M_PI * freq / SAMPLE_RATE);
13
+}
14
+
15
+float sine_osc_sample(struct SineOsc *osc) {
16
+	osc->s0 = osc->s0 - osc->a * osc->s1;
17
+	osc->s1 = osc->s1 + osc->a * osc->s0;
18
+	return osc->s0;
19
+}

+ 12
- 0
sineosc.h View File

@@ -0,0 +1,12 @@
1
+#ifndef SINEOSC_H_
2
+#define SINEOSC_H_
3
+
4
+struct SineOsc {
5
+	float a, s0, s1;
6
+};
7
+
8
+void sine_osc_init(struct SineOsc *osc);
9
+void sine_osc_set_freq(struct SineOsc *osc, float freq);
10
+float sine_osc_sample(struct SineOsc *osc);
11
+
12
+#endif /* SINEOSC_H_ */

+ 139
- 48
synth.c View File

@@ -1,82 +1,159 @@
1 1
 #include <stdio.h>
2 2
 #include <string.h>
3
+#include <stdlib.h>
4
+#include <math.h>
3 5
 
4 6
 #include "synth.h"
5 7
 #include "config.h"
6 8
 
7 9
 #include "tables.inc"
8 10
 
9
-// convert from 16.16 frequency to 16.16 period in samples
10
-static fixed freq2period(fixed freq) {
11
-	uint64_t tmp = (uint64_t)SAMPLE_RATE << 32;
12
-	return tmp / freq;
13
-}
14
-
15 11
 void synth_init(struct Synth *synth) {
16 12
 	synth_set_cutoff_freq(synth, 127);
17 13
 	synth_set_resonance(synth, 0);
14
+	srandom(1234);
15
+	synth->key_stack_size = 0;
16
+	synth->tuning = 440.0;
17
+	synth->volume = 1.0;
18
+	synth->pitch_bend = 0.0;
19
+	synth->lfo_depth = 0.0;
20
+	sine_osc_init(&synth->lfo_osc);
21
+	for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
22
+		synth->voices[i].synth = synth;
23
+	}
18 24
 }
19 25
 
20
-uint8_t midi_notes[128];
21
-void synth_note_on(struct Synth *synth, uint8_t note, uint8_t velocity) {
22
-	if(synth->monophonic) {
23
-		int freq = midi_note_freq_fixed[note];
24
-		int freq_below = freq - midi_note_freq_fixed[note - 1];
25
-		int freq_above = midi_note_freq_fixed[note + 1] - freq;
26
-		synth->voices[0].osc.freq = freq;
27
-		synth->voices[0].osc.period = freq2period(freq);
28
-		for(int i = 1; i <= 3; i++) {
29
-			struct Voice *voice = synth->voices + i;
30
-			voice->osc.freq = freq - synth->unison_spread * freq_below * i / 512;
31
-			voice->osc.period = freq2period(voice->osc.freq);
32
-		}
33
-		for(int i = 4; i < 7; i++) {
34
-			struct Voice *voice = synth->voices + i;
35
-			voice->osc.freq = freq + synth->unison_spread * freq_above * (i - 3) / 512;
36
-			voice->osc.period = freq2period(voice->osc.freq);
37
-		}
26
+static float detune(float freq, float semitones) {
27
+	return freq * pow(2, semitones / 12.0);
28
+}
38 29
 
39
-		synth->voices[0].pan = 0;
40
-		for(int i = 1; i <= 7; i++) {
41
-			synth->voices[i].pan = ((i&1) * 2 - 1) * synth->stereo_spread * ((i + 1) / 2) / 3;
42
-		}
30
+static float midifreq(uint8_t note) {
31
+	return pow(2, (note - 69) / 12.0) * 440.0;
32
+}
43 33
 
44
-		for(int i = 0; i < 7; i++) {
45
-			struct Voice *voice = synth->voices + i;
46
-			voice->osc.phase = random();
34
+static void synth_set_pitch(struct Synth *synth) {
35
+	float lfo_detune = synth->lfo_depth * sine_osc_sample(&synth->lfo_osc);
36
+	for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
37
+		struct Voice *voice = &synth->voices[i];
38
+		if(voice->osc_env.state != None)
39
+			oscillator_set_freq(&voice->osc, detune(midifreq(voice->note), voice->detune + synth->pitch_bend * synth->pitch_bend_range + lfo_detune));
40
+	}
41
+}
47 42
 
48
-			voice->osc_env.attack = synth->osc_env.attack;
49
-			voice->osc_env.decay = synth->osc_env.decay;
50
-			voice->osc_env.sustain = synth->osc_env.sustain;
51
-			voice->osc_env.release = synth->osc_env.release;
43
+static void synth_note_on_monophonic(struct Synth *synth, uint8_t note, uint8_t velocity) {
44
+	synth->voices[0].detune = 0;
45
+	for(int i = 1; i <= 3; i++) {
46
+		synth->voices[i].detune = i * synth->unison_spread / 6.0;
47
+	}
48
+	for(int i = 4; i < 7; i++) {
49
+		synth->voices[i].detune = (i - 3) * synth->unison_spread / 6.0;
50
+	}
51
+
52
+	synth->voices[0].pan = 0;
53
+	for(int i = 1; i <= 7; i++) {
54
+		synth->voices[i].pan = ((i&1) * 2 - 1) * synth->stereo_spread * ((i + 1) / 2) / 3;
55
+	}
52 56
 
53
-			voice->filter_env.attack = synth->filter_env.attack;
54
-			voice->filter_env.decay = synth->filter_env.decay;
55
-			voice->filter_env.sustain = synth->filter_env.sustain;
56
-			voice->filter_env.release = synth->filter_env.release;
57
+	for(int i = 0; i < 7; i++) {
58
+		struct Voice *voice = synth->voices + i;
59
+		voice->osc.phase = random();
60
+
61
+		voice->osc_env.attack = synth->osc_env.attack;
62
+		voice->osc_env.decay = synth->osc_env.decay;
63
+		voice->osc_env.sustain = synth->osc_env.sustain;
64
+		voice->osc_env.release = synth->osc_env.release;
65
+
66
+		voice->filter_env.attack = synth->filter_env.attack;
67
+		voice->filter_env.decay = synth->filter_env.decay;
68
+		voice->filter_env.sustain = synth->filter_env.sustain;
69
+		voice->filter_env.release = synth->filter_env.release;
70
+
71
+		voice_note_start(voice, note, i == 0 ? velocity : velocity / 4);
72
+	}
73
+}
57 74
 
58
-			voice_note_start(voice, note, i == 0 ? velocity : velocity / 4);
75
+void synth_note_on(struct Synth *synth, uint8_t note, uint8_t velocity) {
76
+	if(synth->monophonic) {
77
+		synth->key_stack[synth->key_stack_size].note = note;
78
+		synth->key_stack[synth->key_stack_size].velocity = velocity;
79
+		synth->key_stack_size++;
80
+		if(synth->key_stack_size >= SYNTH_NUM_VOICES) {
81
+			memmove(synth->key_stack, synth->key_stack + 1, sizeof(synth->key_stack[0]) * (SYNTH_NUM_VOICES - 1));
82
+			synth->key_stack_size--;
83
+		}
84
+		synth_note_on_monophonic(synth, note, velocity);
85
+	} else {
86
+		struct Voice *found = 0;
87
+		uint32_t oldest_time = 0;
88
+		for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
89
+			struct Voice *voice = &synth->voices[i];
90
+			if(voice->osc_env.state == None) {
91
+				found = voice;
92
+				break;
93
+			}
94
+			if(voice->time > oldest_time) {
95
+				oldest_time = voice->time;
96
+				found = voice;
97
+			}
59 98
 		}
99
+		found->osc_env.attack = synth->osc_env.attack;
100
+		found->osc_env.decay = synth->osc_env.decay;
101
+		found->osc_env.sustain = synth->osc_env.sustain;
102
+		found->osc_env.release = synth->osc_env.release;
103
+
104
+		found->filter_env.attack = synth->filter_env.attack;
105
+		found->filter_env.decay = synth->filter_env.decay;
106
+		found->filter_env.sustain = synth->filter_env.sustain;
107
+		found->filter_env.release = synth->filter_env.release;
108
+
109
+		voice_note_start(found, note, velocity);
60 110
 	}
111
+
61 112
 }
62 113
 
63
-void synth_note_off(struct Synth *synth, uint8_t note, uint8_t velocity) {
64
-	(void)velocity;
114
+static void synth_note_off_monophonic(struct Synth *synth) {
65 115
 	for(int i = 0; i < 7; i++) {
66 116
 		struct Voice *voice = synth->voices + i;
67 117
 		voice_stop(voice);
68 118
 	}
69 119
 }
70 120
 
121
+void synth_note_off(struct Synth *synth, uint8_t note, uint8_t velocity) {
122
+	if(synth->monophonic) {
123
+		if(synth->key_stack_size > 1) {
124
+			synth_note_on_monophonic(synth, synth->key_stack[synth->key_stack_size - 2].note, synth->key_stack[synth->key_stack_size - 2].velocity);
125
+		} else {
126
+			synth_note_off_monophonic(synth);
127
+		}
128
+		synth->key_stack_size--;
129
+	} else {
130
+		for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
131
+			struct Voice *voice = synth->voices + i;
132
+			if(voice->note == note && voice->osc_env.state != None && voice->osc_env.state != Release) {
133
+				voice_stop(&synth->voices[i]);
134
+			}
135
+		}
136
+		printf("voices: ");
137
+		for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
138
+			printf("%d%d ", synth->voices[i].osc_env.state, synth->voices[i].filter_env.state);
139
+		}
140
+		printf("\n");
141
+	}
142
+}
143
+
71 144
 void synth_render_sample(struct Synth *synth, float *out) {
72 145
 	float smpl[2] = { 0, 0 };
73 146
 
147
+	synth_set_pitch(synth);
148
+
74 149
 	for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
75
-		struct Voice *v = synth->voices + i;
150
+		struct Voice *v = &synth->voices[i];
151
+		if(v->osc_env.state == None) continue;
152
+
76 153
 		float vsmpl[2];
77 154
 		voice_render_sample(v, vsmpl);
78 155
 		for(int j = 0; j < 2; j++) {
79
-			smpl[j] += vsmpl[j] / 2.0;
156
+			smpl[j] += vsmpl[j];
80 157
 			if(smpl[j] > 1) smpl[j] = 1;
81 158
 			else if(smpl[j] < -1) smpl[j] = -1;
82 159
 		}
@@ -84,17 +161,16 @@ void synth_render_sample(struct Synth *synth, float *out) {
84 161
 
85 162
 	out[0] = smpl[0];
86 163
 	out[1] = smpl[1];
164
+	synth->time++;
87 165
 }
88 166
 
89 167
 void synth_set_cutoff_freq(struct Synth *synth, uint8_t f) {
90
-	for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
91
-		filter_set_cutoff(&synth->voices[i].filter, f);
92
-	}
168
+	synth->cutoff = f / 127.0;
93 169
 }
94 170
 
95 171
 void synth_set_resonance(struct Synth *synth, uint8_t f) {
96 172
 	for(int i = 0; i < SYNTH_NUM_VOICES; i++) {
97
-		filter_set_resonance(&synth->voices[i].filter, f);
173
+		filter_set_resonance(&synth->voices[i].filter, f / 127.0);
98 174
 	}
99 175
 }
100 176
 
@@ -105,3 +181,18 @@ void synth_set_unison_spread(struct Synth *synth, uint8_t w) {
105 181
 void synth_set_stereo_spread(struct Synth *synth, uint8_t w) {
106 182
 	synth->stereo_spread = w;
107 183
 }
184
+
185
+void synth_set_volume(struct Synth *s, uint8_t vol) {
186
+	s->volume = vol / 127.0;
187
+}
188
+
189
+void synth_pitch_bend(struct Synth *s, int16_t bend) {
190
+	s->pitch_bend = bend / 8191.0;
191
+	if(s->pitch_bend < -1.0) s->pitch_bend = -1.0;
192
+	if(s->pitch_bend > 1.0) s->pitch_bend = 1.0;
193
+	synth_set_pitch(s);
194
+}
195
+
196
+void synth_set_lfo_depth(struct Synth *s, uint8_t mod) {
197
+	s->lfo_depth = mod / 127.0;
198
+}

+ 20
- 1
synth.h View File

@@ -11,6 +11,11 @@ typedef uint32_t fixed;
11 11
 #include "filter.h"
12 12
 #include "oscillator.h"
13 13
 #include "voice.h"
14
+#include "sineosc.h"
15
+
16
+struct Key {
17
+	uint8_t note, velocity;
18
+};
14 19
 
15 20
 struct Synth {
16 21
 	struct Voice voices[SYNTH_NUM_VOICES];
@@ -18,6 +23,17 @@ struct Synth {
18 23
 	uint8_t unison_spread;
19 24
 	uint8_t stereo_spread;
20 25
 	uint8_t monophonic;
26
+
27
+	float tuning; // 440.0Hz
28
+	float pitch_bend_range;
29
+	float cutoff, filter_eg_intensity, filter_kbd_track, lfo_freq;
30
+
31
+	// private
32
+	struct Key key_stack[SYNTH_NUM_VOICES];
33
+	struct SineOsc lfo_osc;
34
+	uint8_t key_stack_size;
35
+	float volume, pitch_bend, lfo_depth;
36
+	uint32_t time;
21 37
 };
22 38
 
23 39
 void synth_init(struct Synth *synth);
@@ -28,6 +44,9 @@ void synth_set_pulse_width(struct Synth *s, uint8_t width);
28 44
 void synth_set_unison_spread(struct Synth *s, uint8_t spread);
29 45
 void synth_set_stereo_spread(struct Synth *s, uint8_t spread);
30 46
 void synth_set_cutoff_freq(struct Synth *s, uint8_t freq);
31
-void synth_set_resonance(struct Synth *s, uint8_t freq);
47
+void synth_set_resonance(struct Synth *s, uint8_t res);
48
+void synth_set_volume(struct Synth *s, uint8_t vol);
49
+void synth_pitch_bend(struct Synth *s, int16_t bend);
50
+void synth_set_lfo_depth(struct Synth *s, uint8_t mod);
32 51
 
33 52
 #endif /* SYNTH_H_ */

+ 4
- 3
voice.c View File

@@ -1,16 +1,16 @@
1
-#include "voice.h"
1
+#include "synth.h"
2 2
 
3 3
 void voice_render_sample(struct Voice *v, float *out) {
4 4
 	//if(v->osc_env.state == None) return;
5 5
 	float amplitude = envelope_sample(&v->osc_env); // calculate based on key velocity and envelope
6 6
 	float cutoff = envelope_sample(&v->filter_env);
7 7
 
8
-	int32_t ret[2] = { 0, 0 };
9 8
 	float s = oscillator_render_sample(&v->osc);
10
-	filter_set_cutoff(&v->filter, cutoff * 127);
9
+	filter_set_cutoff(&v->filter, v->synth->cutoff + cutoff * v->synth->filter_eg_intensity);
11 10
 	float f = filter_sample(&v->filter, v->volume * amplitude * s / 32768.0);
12 11
 	out[0] = (127 + v->pan) * f / 255.0;
13 12
 	out[1] = (127 - v->pan) * f / 255.0;
13
+	v->time++;
14 14
 }
15 15
 
16 16
 void voice_note_start(struct Voice *voice, uint8_t note, uint8_t velocity) {
@@ -20,6 +20,7 @@ void voice_note_start(struct Voice *voice, uint8_t note, uint8_t velocity) {
20 20
 	envelope_start(&voice->filter_env);
21 21
 
22 22
 	note &= 0x7f;
23
+	voice->time = 0;
23 24
 	voice->note = note;
24 25
 	voice->osc.sub_phase = voice->osc.phase;
25 26
 	voice->osc.sub_oct = 1;

+ 5
- 0
voice.h View File

@@ -6,10 +6,15 @@
6 6
 #include "oscillator.h"
7 7
 #include "filter.h"
8 8
 
9
+struct Synth;
9 10
 struct Voice {
11
+	struct Synth *synth;
12
+
10 13
 	uint8_t note;
14
+	float detune;
11 15
 	float volume;
12 16
 	int8_t pan;
17
+	uint32_t time;
13 18
 
14 19
 	struct Envelope osc_env, filter_env;
15 20
 	struct Oscillator osc;

Loading…
Cancel
Save