Skip to content

Commit

Permalink
Added drum synth
Browse files Browse the repository at this point in the history
  • Loading branch information
stg committed Jun 20, 2012
1 parent 7f2a09b commit 07188a7
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 54 deletions.
44 changes: 44 additions & 0 deletions arduino-sketches/drumstix/README
@@ -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
157 changes: 157 additions & 0 deletions arduino-sketches/drumstix/drumstix.ino
@@ -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);
}
36 changes: 36 additions & 0 deletions arduino-sketches/drumstix/midi_info.txt
@@ -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)
58 changes: 4 additions & 54 deletions arduino-sketches/supersaw_sylt/supersaw_sylt.ino
Expand Up @@ -432,32 +432,7 @@ void loop( void ) {
Synth.setShift( 0, ( 255 - midi->data2 ) >> 1 );
break;
case 13: // F0 style
switch( midi->data2 / 22 ) {
case 0: // low-pass
Synth.setFilter( 0, FILTER_LP );
Synth.setMode( 0, 0 );
break;
case 1: // fat low-pass
Synth.setFilter( 0, FILTER_LP );
Synth.setMode( 0, 3 );
break;
case 2: // band-pass
Synth.setFilter( 0, FILTER_BP );
Synth.setMode( 0, 0 );
break;
case 3: // fat band-pass
Synth.setFilter( 0, FILTER_BP );
Synth.setMode( 0, 3 );
break;
case 4: // high-pass
Synth.setFilter( 0, FILTER_HP );
Synth.setMode( 0, 2 );
break;
case 5: // phaser
Synth.setFilter( 0, FILTER_HP );
Synth.setMode( 0, 0 );
break;
}
Synth.setFilterMode( 0, midi->data2 / 22 );
break;

case 15: // F1 center frequency
Expand All @@ -471,34 +446,9 @@ void loop( void ) {
Synth.setShift( 1, ( 255 - midi->data2 ) >> 1 );
break;
case 18: // F1 style
switch( midi->data2 / 22 ) {
case 0: // low-pass
Synth.setFilter( 1, FILTER_LP );
Synth.setMode( 1, 0 );
break;
case 1: // fat low-pass
Synth.setFilter( 1, FILTER_LP );
Synth.setMode( 1, 3 );
break;
case 2: // band-pass
Synth.setFilter( 1, FILTER_BP );
Synth.setMode( 1, 0 );
break;
case 3: // fat band-pass
Synth.setFilter( 1, FILTER_BP );
Synth.setMode( 1, 3 );
break;
case 4: // high-pass
Synth.setFilter( 1, FILTER_HP );
Synth.setMode( 1, 2 );
break;
case 5: // phaser
Synth.setFilter( 1, FILTER_HP );
Synth.setMode( 1, 0 );
break;
}
Synth.setFilterMode( 1, midi->data2 / 22 );
break;

case 20: // Pitch portamento speed
port_speed = 127-midi->data2;
break;
Expand Down Expand Up @@ -657,4 +607,4 @@ void loop( void ) {
}
}

}
}

0 comments on commit 07188a7

Please sign in to comment.