Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
241 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
Drum synth | ||
|
||
== MIDI MAPPING ================== | ||
|
||
CC Description Values | ||
10 Pitch end 0..127=0-6kHz | ||
15 Pitch start 0..127=0-6kHz | ||
|
||
11 Volume end 0..127=0-100% | ||
16 Volume start 0..127=0-100% | ||
|
||
12 F0 end 0..127=0-20kHz | ||
17 F0 start 0..127=0-20kHz | ||
|
||
13 F1 end 0..127=0-20kHz | ||
18 F1 start 0..127=0-20kHz | ||
|
||
20 F0 resonance 0..127=0-100% | ||
21 F0 mode see modes | ||
|
||
22 F1 resonance 0..127=0-100% | ||
23 F1 mode see modes | ||
|
||
25 waveform see waveform | ||
26 pulse width 0..127=0-100% | ||
27 time 0..127=0-2sec | ||
|
||
== WAVEFORMS ===================== | ||
|
||
Range Waveform | ||
0...31 noise | ||
32...63 saw | ||
64...95 triangle | ||
96..127 pulse/square | ||
|
||
== MODES ========================= | ||
|
||
Range Filter mode | ||
0...21 low-pass | ||
22...43 phat low-pass | ||
44...65 band-pass | ||
66...87 phat band-pass | ||
88..109 high-pass | ||
110..127 phaser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#include "Synth.h" | ||
|
||
#define SAMPLE_FREQ 10000 | ||
|
||
typedef struct { | ||
float a; | ||
float b; | ||
} env_t; | ||
|
||
typedef struct { | ||
uint8_t wf; | ||
env_t vol; | ||
env_t pitch; | ||
} osc_t; | ||
|
||
typedef struct { | ||
env_t freq; | ||
uint8_t type; | ||
uint8_t mode; | ||
uint8_t q; | ||
} flt_t; | ||
|
||
typedef struct { | ||
osc_t osc; | ||
flt_t flt[2]; | ||
float time; | ||
} drum_t; | ||
|
||
drum_t drummer; | ||
|
||
drum_t drum; | ||
uint32_t delta_sg=0, delta_time=0; | ||
float osc, vol; | ||
uint8_t randy[256]; | ||
uint8_t pulse = 192; | ||
|
||
uint8_t sample(void) { | ||
int8_t out; | ||
if(delta_sg) { | ||
osc += drum.osc.pitch.a; | ||
if(osc >= 1.0) osc -= 1.0; | ||
switch(drum.osc.wf) { | ||
case 0: | ||
out = randy[(uint8_t)(osc * 0xFF)]; | ||
break; | ||
case 1: | ||
out = ((uint8_t)(osc * 0xFF)) ^ 0x80; | ||
break; | ||
case 2: | ||
out = ((uint8_t)(osc > 0.5 ? ((1.0 - osc) * 0x200) : (osc * 0x200))) ^ 0x80; | ||
break; | ||
default: | ||
out = (uint8_t)(osc * 0x7F) > (drum.osc.wf & 0x7F) ? 127 : -128; | ||
break; | ||
} | ||
|
||
drum.osc.pitch.a += drum.osc.pitch.b; | ||
delta_sg--; | ||
|
||
return ((uint8_t)(out*vol))^0x80; | ||
} else{ | ||
return 0x80; | ||
} | ||
} | ||
|
||
void setup(void) { | ||
uint8_t n=0; | ||
|
||
// generate some randoms for noise | ||
do { randy[n] = rand(); } while(++n); | ||
|
||
// TIMING | ||
drummer.time = 1.0; // time, seconds | ||
|
||
// OSCILLATOR | ||
drummer.osc.wf = 0; // waveform | ||
// 0=noise | ||
// 1=saw | ||
// 2=triangle | ||
// 128-255=var. pulse (192=square) | ||
drummer.osc.pitch.a = 100.0; // start pitch, hz | ||
drummer.osc.pitch.b = 10.0; // end pitch, hz | ||
drummer.osc.vol.a = 0.0; // start volume, 0-1 | ||
drummer.osc.vol.b = 1.0; // end volume, 0-1 | ||
|
||
// FILTER 0 | ||
drummer.flt[0].mode = FM_FATLP; // filter mode FM_LP/FATLP/BP/FATBP/HP/PHASER | ||
drummer.flt[0].q = 50; // resonance, 0-63 | ||
drummer.flt[0].freq.a = 4000.0; // start cutoff, hz | ||
drummer.flt[0].freq.b = 50; // end cutoff, hz | ||
|
||
// FILTER 1 | ||
drummer.flt[1].mode = FM_FATLP; // see filter 0 | ||
drummer.flt[1].q = 50; // see filter 0 | ||
drummer.flt[1].freq.a = 4000.0; // see filter 0 | ||
drummer.flt[1].freq.b = 50.0; // see filter 0 | ||
|
||
Synth.attachInterrupt(sample, SAMPLE_FREQ); | ||
} | ||
|
||
float midi_range(uint8_t cc, float a, float b) { | ||
return (((float)cc) / 127.0) * (b - a) + a; | ||
} | ||
|
||
void loop(void) { | ||
midi_t *midi = Synth.getMidi(); | ||
uint8_t n; | ||
uint32_t delta; | ||
if(midi) { | ||
if(midi->message == 0x90) { | ||
// MIDI: NOTE ON | ||
cli(); | ||
drum = drummer; | ||
delta_time = drum.time * SAMPLE_FREQ; | ||
delta_sg = delta_time; | ||
for(n=0;n!=2;n++) { | ||
drum.flt[n].freq.b = (drum.flt[n].freq.b - drum.flt[n].freq.a) / (drum.time * SAMPLE_FREQ); | ||
Synth.setResonance(n, drum.flt[n].q); | ||
Synth.setFilterMode(n, drum.flt[n].mode); | ||
} | ||
osc = (drum.osc.wf == 2) ? 0.25 : 0.0; | ||
drum.osc.vol.b = (drum.osc.vol.b - drum.osc.vol.a) / (drum.time * SAMPLE_FREQ); | ||
drum.osc.pitch.a /= SAMPLE_FREQ; | ||
drum.osc.pitch.b = ((drum.osc.pitch.b / SAMPLE_FREQ) - drum.osc.pitch.a) / (drum.time * SAMPLE_FREQ); | ||
vol = drum.osc.vol.a; | ||
sei(); | ||
} else if(midi->message == 0xB0) { | ||
// MIDI: CONTROL CHANGE | ||
switch(midi->data1) { | ||
case 10: drummer.osc.pitch.b = midi_range(midi->data2, 0, 6000); break; | ||
case 15: drummer.osc.pitch.a = midi_range(midi->data2, 0, 6000); break; | ||
case 11: drummer.osc.vol.b = midi_range(midi->data2, 0, 1); break; | ||
case 16: drummer.osc.vol.a = midi_range(midi->data2, 0, 1); break; | ||
case 12: drummer.flt[0].freq.b = midi_range(midi->data2, 10, 19990); break; | ||
case 17: drummer.flt[0].freq.a = midi_range(midi->data2, 10, 19990); break; | ||
case 13: drummer.flt[1].freq.b = midi_range(midi->data2, 10, 19990); break; | ||
case 18: drummer.flt[1].freq.a = midi_range(midi->data2, 10, 19990); break; | ||
case 20: drummer.flt[0].q = midi->data2 >> 2; break; | ||
case 21: drummer.flt[0].mode = midi->data2 / 22; break; | ||
case 22: drummer.flt[1].q = midi->data2 >> 2; break; | ||
case 23: drummer.flt[0].mode = midi->data2 / 22; break; | ||
case 25: drummer.osc.wf = midi->data2 >> 5; break; | ||
case 26: pulse = midi->data2 | 0x80; break; | ||
case 27: drummer.time = midi_range(midi->data2, 0.05, 2); break; | ||
} | ||
if(drummer.osc.wf > 2) drummer.osc.wf = pulse; | ||
} | ||
Synth.freeMidi(); | ||
} | ||
// slow update of volume, cutoff - offloads sample generation interrupt | ||
cli(); | ||
delta = delta_time - delta_sg; | ||
sei(); | ||
vol = drum.osc.vol.a + drum.osc.vol.b * delta; | ||
Synth.setCutoff(0, drum.flt[0].freq.a + drum.flt[0].freq.b * delta); | ||
Synth.setCutoff(1, drum.flt[1].freq.a + drum.flt[0].freq.b * delta); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
1 supersaw Spread | ||
|
||
10 f0 cutoff | ||
11 f0 resonance | ||
12 f0 frequency shift | ||
13 f0 mode (will change) | ||
|
||
15 f1 cutoff | ||
16 f1 resonance | ||
17 f1 frequency shift | ||
18 f1 mode (will change) | ||
|
||
20 portamento rate | ||
21 volume envelope initial level | ||
22 volume envelope attack rate | ||
23 volume envelope decay rate | ||
24 volume envelope sustain level | ||
25 volume envelope release rate | ||
|
||
29 mode (0-63: mono, 64-127: poly) | ||
|
||
30 f0 tracking (0: envelope, 1-127: key tracking rate) | ||
31 f0 envelope initial level | ||
32 f0 envelope attack rate | ||
33 f0 envelope decay rate | ||
34 f0 envelope sustain level | ||
35 f0 envelope release rate | ||
36 f0 envelope multiplier (0-63: negative, 65-127: positive) | ||
|
||
40 f1 tracking (0: envelope, 1-127: key tracking rate) | ||
41 f1 envelope initial level | ||
42 f1 envelope attack rate | ||
43 f1 envelope decay rate | ||
44 f1 envelope sustain level | ||
45 f1 envelope release rate | ||
46 f1 envelope multiplier (0-63: negative, 65-127: positive) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters