//HSS3S02V10 for use with HSS3f hardware.
//gijs gieskes 2009/2010, http://gieskes.nl
//credits: http://gieskes.nl/instruments/files/hard-soft-synth-3/hss3-credits.html
//infra red
#define BITS_PER_MESSAGE 12
#define B_1 900
#define B_0 1400
#define START_BIT 2000
#define IR_PIN 2
//find the threshold time b/w the two pulse sizes
#define BIT_THRESH B_0+((B_1-B_0)/2)
//midi library:
//http://timothytwillman.com/itp_blog/?page_id=240
#include "Midi.h"
class MyMidi : public Midi {
public:
// Need this to compile; it just hands things off to the Midi class.
MyMidi(HardwareSerial &s) : Midi(s) {}
void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
{
//midiHandler(channel, note, true);
}
void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
{
//midiHandler(channel, note, false);
}
};
MyMidi midi(Serial);
byte midichannel = 1;
//pots mounted on top == true, bottom == false;
boolean reverse = false;
//wave generator values
static byte decayA = 0;
static int octaver = 0;
byte butSel = 0;
byte prevSynth = 100;
byte triggerDecay = 0;
int sinAc = 0;
byte sinAc2 = 0;
char cvol = 0;
float tvol = 0.5;
float tvol2 = 0;
float kick = 0;
int BA = 0;
int BB = 0;
int tp = 0;
//oscs
unsigned int oscA = 0;
unsigned int oscB = 0;
unsigned int oscC = 0;
unsigned int oscD = 0;
unsigned int oscA2 = 0;
unsigned int oscB2 = 0;
unsigned int oscC2 = 0;
unsigned int oscD2 = 0;
boolean ta = LOW;
boolean tb = LOW;
boolean tc = LOW;
int oscL[8] = {264,264,264,264,264,264,264,264};
//noise synth waveform holder
byte oscN[8] = {1,1,1,1,1,1,1,1};
//pot array
int pot[8] = {0,0,0,0,0,0,0,0};
float sinA[32] = {0.6, 0.679, 0.755, 0.825, 0.886, 0.936, 0.972, 0.994, 1, 0.99, 0.965, 0.926, 0.874, 0.811, 0.739, 0.662, 0.583, 0.504, 0.429, 0.361, 0.303, 0.256, 0.222, 0.204, 0.201, 0.214, 0.242, 0.284, 0.339, 0.404, 0.477, 0.554};
byte waveTable[512];
/*
int major[] =
{253, 238, 212, 189, 179, 159, 141, 126, 119, 106, 94, 89, 79, 70, 63, 59, 53, 47, 44, 39, 35, 31, 29, 26, 23};
byte major[2][26] = {
{239, 213, 190, 160, 142, 127, 120, 107, 95, 89, 80, 71, 64, 60, 53, 47, 45, 40, 36, 32, 32, 30, 27, 24, 22, 20}, //C major
{213, 190, 169, 160, 142, 127, 113, 107, 95, 84, 80, 71, 64, 56, 53, 47, 42, 40, 36, 32, 28, 27, 24, 21, 22, 20} //D major
};
*/
byte major[3][25] = {
//{239, 213, 190, 160, 142, 127, 120, 107, 95, 89, 80, 71, 64, 60, 53, 47, 45, 40, 36, 32, 32, 30, 27, 24, 22}, //C major
{ 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23, 24, 26, 28, 29, 31, 35, 36, 38, 40, 41, 43}, //C major
//{213, 190, 169, 160, 142, 127, 113, 107, 95, 84, 80, 71, 64, 56, 53, 47, 42, 40, 36, 32, 28, 27, 24, 21, 22}, //D major
{ 2, 4, 6, 7, 9, 11, 14, 16, 18, 19, 21, 23, 26, 28, 30, 31, 33, 36, 39, 41, 43, 44, 46, 48, 48}, //D major
//{226, 201, 190, 169, 150, 134, 127, 113,100, 95, 84, 75, 67, 64, 56, 50, 47, 42, 38, 34, 32, 28, 25, 24, 21} //B major
{ 1, 3, 4, 6, 8, 10, 11, 13, 15, 16, 18, 20, 22, 23, 25, 27, 28, 30, 32, 34, 33, 35, 37, 38, 40} //B major
};
byte scale[49] = {
//0 1 2 3 4 5 6 7 8 9 10 11
239, 226, 213, 201, 190, 179, 169, 160, 150, 142, 134, 127,
//12 13 14 15 16 17 18 19 20 21 22 23
120, 113, 107, 100, 95, 89, 84, 80, 75, 71, 67, 64,
//24 25 26 27 28 29 30 31 32 33 34 35
60, 56, 53, 50, 47, 45, 42, 40, 38, 36, 34, 32,
//36 37 38 39 40 41 42 43 44 45 46 47
30, 28, 27, 25, 24, 22, 21, 19, 18, 17, 16, 16,
//48
15
};
//if OCR0A == 255
//6: c=15
//5: b=16 a#=17 a=18 g#=19 g=20 f#=21 f=22 e=24 d#=25 d=27 c#=28 c=30
//4: b=32 a#=34 a=36 g#=38 g=40 f#=42 f=45 e=47 d#=50 d=53 c#=56 c=60
//3: b=64 a#=67 a=71 g#=75 g=80 f#=84 f=89 e=95 d#=100 d=107 c#=113 c=120
//2: b=127 a#=134 a=142 g#=150 g=160 f#=169 f=179 e=190 d#=201 d=213 c#=226 c=239
float sinC[41];
byte ti = 0;
int out = 0;
byte selPitch = 0;
//trigger vars
volatile boolean externalTrigger = false;
volatile boolean triggerActive = false;
volatile boolean inLoop = false;
byte sampleRate = 255;
void setup(){
//TIMER SETUP
cli();
TCCR1B = TCCR1B & B11111000 | B00000001;
TCCR2B = TCCR2B & B11111000 | B00000001;
//also check the datasheet!
TCCR0A = TCCR0A & B11111000 | B00000010;
TCCR0B = TCCR0B & B11111000 | B00000010;
TIMSK0 = TIMSK0 & B11111000 | B00000010; //Call ISR
//set sample rate/frequency
OCR0A = sampleRate;
sei();
for(byte i=0; i<128; i+=8){
sinC[ti] = i;
ti++;
}
for(byte i=0; i<128; i+=8){
sinC[ti] = i;
ti++;
}
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(13, OUTPUT);
pinMode(3, OUTPUT);
readAnalogs();
resetWavetable();
pinMode(2, INPUT);
digitalWrite(2, HIGH);
//set to CHANGE to patch signal direct thrue..
attachInterrupt(0, triggerOut, CHANGE);
midi.begin(0);
//Serial.begin(9600);
}
//From TIMSK2
ISR(TIMER0_COMPA_vect) {
switch (butSel){
case 0:
droneI0();
break;
case 1:
droneI1();
break;
case 2:
droneI2();
break;
case 3:
teknoI0();
break;
case 4:
arpegiatorI1();
break;
case 5:
drumsI0();
break;
case 6:
arpegiatorI0();
break;
case 7:
hnoiseI0();
break;
case 8:
clicksI0();
break;
case 9:
feedbackI0();
break;
case 10:
remoteI0();
break;
case 11:
remoteI1();
break;
}
}
void loop(){
//check if we are in the loop.. (for interupt, pullup resistors).
inLoop = true;
butSel = map(pot[5], 0, 1023, 0, 11);
//read potmeters
readAnalogs();
switch (butSel){
case 0:
droneL0();
break;
case 1:
droneL1();
break;
case 2:
droneL2();
break;
case 3:
teknoL0();
break;
case 4:
arpegiatorL1();
break;
case 5:
drumsL0();
break;
case 6:
arpegiatorL0();
break;
case 7:
hnoiseL0();
break;
case 8:
clicksL0();
break;
case 9:
feedbackL0();
break;
case 10:
remoteL0();
break;
case 11:
remoteL1();
break;
}
}
void droneI0(){
OCR0A = 180;//sampleRate;
oscA = cup(oscA, max((pot[1] >> 1), 1));
oscB = cup(oscB, max((pot[2] >> 1), 1));
oscC = cup(oscC, max((pot[3] >> 1), 1));
//mix oscillators
out = ((waveTable[oscA]*2)+(waveTable[oscB]*2)+(waveTable[oscC]*2)) >> 2; //was /7
analogWrite(9, out);
}
void droneL0(){
waveGenartor(31, (pot[4] >> 4));
if(pot[0] && pot[0] < 1022){
if(!oscB2 && !externalTrigger || triggerActive){
triggerActive = false;
ta = !ta;
digitalWrite(11, ta);
trigger(2);
}
oscB2++;
oscB2 %= pot[0]+1;
}else if(pot[0]){
digitalWrite(11, LOW);
}else{
digitalWrite(11, HIGH);
}
analogWrite(10, out);
delayMicroseconds(30);
}
void droneI1(){
//fixed, if not it will slow down..
OCR0A = 255;
oscA2 = map(pot[1], 0, 1023, 16, 0);
//detunes oscillators
oscA++;
oscA += (1023 - pot[4])>>7;
oscA %= (scale[major[1][oscA2]]);
oscB = cup(oscB, (scale[major[1][oscA2]])-1);
oscC = cup(oscC, (scale[major[1][oscA2]])-2);
sendMidi(major[1][oscA2]+36, 100);
//mix oscillators
out = ((waveTable[oscA])+(waveTable[oscB]*2)+(waveTable[oscC]*2)) >> 3;
analogWrite(9, out);
}
void droneL1(){
analogWrite(11, ((1023 - pot[0]) >> 2));
waveGenartor2(oscB2);
if(pot[3]){
oscB2++;
oscB2 %= (pot[3]>> 2)+100;
if(!oscB2 && !externalTrigger || triggerActive){
triggerActive = false;
trigger(2);
}
}else{
oscB2 = 150;
}
delayMicroseconds(12);
}
void droneI2(){
//fixed, if not it will slow down..
OCR0A = 255;
oscA = cup(oscA, scale[oscA2] >> 1);
oscB = cup(oscB, scale[oscB2] >> 1);
oscC = cup(oscC, scale[oscC2] >> 1);
/*
oscA++;
oscA %= (scale[oscA2] >> 1);
oscB++;
oscB %= (scale[oscB2] >> 1);
oscC++;
oscC %= (scale[oscC2] >> 1);
*/
//mix oscillators
out = ((waveTable[oscA])+(waveTable[oscB])+(waveTable[oscC])) >> 1;
analogWrite(9, out);
}
void droneL2(){
oscA2 = map(pot[1], 0, 1023, 48, 0);
oscB2 = map(pot[2], 0, 1023, 48, 0);
oscC2 = map(pot[3], 0, 1023, 48, 0);
sendMidi(oscA2+36, 100);
analogWrite(11, ((1023 - pot[0]) >> 2));
waveGenartor2(max(pot[4] >> 1, 8));
delayMicroseconds(12);
}
void teknoI0(){
//techno
OCR0A = 255;
oscB = cup(oscB, (pot[4]<<1)+500);
if(!oscB && !externalTrigger || triggerActive){
triggerActive = false;
trigger(2);
if(externalTrigger){
oscD = ((1023 - pot[4]) >> 8)+1;
}else{
oscD = 4;
}
ta = true;
}
oscD2 = cup(oscD2, 3);
if(!oscD2){
sendMidi(oscA2+36, (byte)tvol);
//legato
if(tp < (scale[oscA2])){
tp++;
}else if(tp > (scale[oscA2])){
tp--;
}
}
//oscillators timer
oscA = cup(oscA, (tp >> 1));
analogWrite(11, constrain(((tp-44) << 1), 0, 255));
//decay
tvol-= 0.05;
tvol = max(tvol, 0);
//saw to square so volume stays sort of the same..
out = constrain((oscA<<1), 0, (byte)tvol);
analogWrite(9, out);
}
void teknoL0(){
//nothing needed here (-:
if(ta){
ta = false;
//reset to start volume.
tvol = 70;
//selectpotmeter for next pitch
selPitch++;
selPitch %= oscD;
oscA2 = map(pot[selPitch], 0, 1023, 48, 0);
}
}
void hnoiseI0(){
OCR0A = (pot[3] >> 4)+191;
//oscillators
oscA = cup(oscA, max(pot[1] >> 1, 3));
oscB = cup(oscA, max((pot[1] >> 1)+1, 4));
out = (((waveTable[oscA])+(waveTable[oscB])) >> 1);
//amplitude modulation trick... a bit noisy but it works..
if(pot[2]){
oscA2 = cup(oscA2, 255);
if(!oscA2){
ta = !ta;
}
oscB2 = cup(oscB2, (((pot[2]) >> 2) + 255));
if(!oscB2){
ta = !ta;
}
}else{
byte i = 0;
ta = true;
}
if(ta){
analogWrite(9, out);
}
}
void hnoiseL0(){
oscC++;
oscC %= 64;
if(!oscC){
sinAc++;
sinAc %= max(pot[1] >> 1, 2);
if(tb){
waveTable[sinAc] = random(70);
}else{
waveTable[sinAc] = 40;
}
}
oscD++;
oscD %= pot[4]+2;
if(!oscD){
tb = !tb;
}
analogWrite(11, (pot[0] >> 2));
delayMicroseconds(100);
}
void drumsI0(){
OCR0A = 255;//(pot[3] >> 4)+191;
//kick pitch down speed
kick += 0.02;
kick = min(kick, 255);
//pitch
oscA++;
oscA %= (byte) (kick); //convert from float to byte
oscB++;
oscB %= (pot[3] >> 3) + 20; //convert from float to byte
oscD++;
oscD %= (pot[4])+500;
if(!oscD && !externalTrigger || triggerActive){
triggerActive = false;
trigger(2);
BA = pot[1] >> 2;
BB = pot[2] >> 2;
tvol = 0;
tvol2 = 0;
kick = (pot[0] >> 3) + 20;
oscA2++;
oscA2 %= 8;
}
//decay
tvol += 0.01;
tvol = min(tvol, 8);
tvol2 += 0.001;
tvol2 = min(tvol2, 8);
//mix all together.
if(!bitRead(BA, oscA2) && !bitRead(BB, oscA2)){
out = (((waveTable[oscB] >> (byte)tvol)+(waveTable[oscA+255] >> (byte)tvol2)) >> 2);
digitalWrite(11, LOW);
}else if(!bitRead(BA, oscA2)){
out = ((waveTable[oscA+255] >> (byte)tvol2) >> 1);
digitalWrite(11, LOW);
}else if(!bitRead(BB, oscA2)){
out = ((waveTable[oscB] >> (byte)tvol) >> 1);
digitalWrite(11, HIGH);
}
analogWrite(9, out);
}
void drumsL0(){
//bas kick and hh noise..
oscC++;
oscC %= 16;//pot[4]+2;
if(!oscC){
sinAc++;
sinAc %= 255;
decayA++;
decayA %= 32;
waveTable[sinAc] = random(50, 150);
waveTable[sinAc+255] = 255*sinA[decayA];
}
delayMicroseconds(10);
}
void arpegiatorI0(){
//2 voice arpegiator
OCR0A = 255;
oscA = cup(oscA, (scale[major[0][oscL[oscB2]]]) << ta);
oscB = cup(oscB, (scale[major[0][oscN[oscC2]]]) << ta);
//saw to square so volume stays sort of the same..
out = constrain((oscA<<1), 0, (byte)tvol);
//mix
out = min((waveTable[oscA]+waveTable[oscB]) >> 2, 255);
if(tb){
//atack
tvol+= 0.05;
if(tvol > 1){
tb = 0;
}
}else{
//decay
tvol-= 0.0005;
tvol = max(tvol, 0);
}
//prevent clipping when switching between instruments..
tvol = min(tvol, 1.06);
out *= tvol;
analogWrite(9, out);
}
void arpegiatorL0(){
oscD2++;
oscD2 %= pot[4]+200;
if(!oscD2 && !externalTrigger || triggerActive){
triggerActive = false;
//if there is externa trigger signals..
if(externalTrigger){
ta = (pot[4]) >> 8;
}else{
ta = 1;
}
for(byte i=0; i<8; i++){
//multiply and make into byte... melody generation..
oscL[i] = map(((byte) (pot[2]*(i+1)) >> 4), 0, 64, 24, 0);
//oscN[i] = map(((oscN[i]+((byte) (pot[3]*(i+1)))) >> 2), 0, 255, 24, 0);
oscN[i] = map(((byte) (pot[3]*(i+1)) >> 4), 0, 64, 24, 0);
}
//select pitch
oscD++;
oscD %= (pot[0] >> 9)+1;
oscC++;
oscC %= (pot[1] >> 9)+1;
if(!oscD){
oscB2++;
oscB2 %= ((pot[0] >> 6)%8)+1;//map(pot[1], 0, 1023, 1, 8);
}
if(!oscC){
oscC2++;
oscC2 %= ((pot[1] >> 6)%8)+1;//map(pot[1], 0, 1023, 1, 8);
}
digitalWrite(11, HIGH);
//reset for atack to prevent click
tb = 1;
trigger(2);
}
oscC++;
oscC %= 16;
if(!oscC){
waveGenartor4(31, ((pot[1] >> 4)+24));
//Serial.println(((pot[1] >> 4)+32), DEC);
}
delayMicroseconds(8);
}
void clicksI0(){
OCR0A = 255;
oscD = cup(oscD, (pot[4] << 1)+500);
if(!oscD && !externalTrigger || triggerActive){
triggerActive = false;
for(byte i=0; i<8; i++){
//multiply and make into byte... melody generation..
//oscL[i] = map(((byte) (pot[2]*(i+1)) >> 2), 0, 64, 24, 0);
//oscN[i] = map(((byte) (pot[3]*(i+1)) >> 2), 0, 64, 24, 0);
oscL[i] = max(((oscL[i]+((byte) (pot[2]*(i+1)))) >> 1), 1);
oscN[i] = max(((oscN[i]+((byte) (pot[3]*(i+1)))) >> 1), 1);
}
//select pitch
oscB2 = cup(oscB2, pot[1] >> 7);
oscC2 = cup(oscC2, (1023 - pot[1]) >> 7);
tvol = 0;
trigger(2);
}
//pitch
oscA = cup(oscA, (oscL[oscB2] >> ((1023 - pot[0]) >> 7))+2);
oscB = cup(oscB, (oscN[oscC2] >> ((1023 - pot[0]) >> 7))+2);
if(!oscA || !oscB){
tc = !tc;
if(tc){
out = (50) >> (byte)tvol;
}else{
out = pot[4] >> 6;
}
}
//must be here to have less hickups
analogWrite(11, oscL[oscB2]);
//tvol += (((pot[0])+1)*0.00002); //0.1; //fix hier...
tvol += ((oscN[oscC2]+40)*0.00006);
tvol = min(tvol, 8);
analogWrite(9, out);
}
void clicksL0(){
oscC++;
oscC %= 16;
if(!oscC){
waveGenartor4(31, 64);
}
}
void feedbackI0(){
//fixed, if not it will slow down..
OCR0A = 255;
//wavtable length
oscA = cup(oscA, (pot[1] >> 1)+1);
//decay
waveTable[oscA] -= (pot[2] >> 4)+32;
//tone
oscB = cup(oscB, (pot[3]>>4)+1);
if(!oscB){
oscB2 = cup(oscB2, (pot[3]%32)+1);
}
waveTable[oscA] += 110*sinA[oscB2];
//amplitude modulation
oscC = cup(oscC, (pot[4])+8);
if(!oscC && !externalTrigger || triggerActive){
triggerActive = false;
oscC2 = cup(oscC2, 32);
//make sure the trigger is not slowing down to much..
trigger(32);
}
if(pot[4]){ //disable if 0
waveTable[oscA] *= sinA[oscC2];
}else{
waveTable[oscA] *= 0.8;
}
out = waveTable[oscA]>>2;
analogWrite(9, out);
}
void feedbackL0(){
oscD = cup(oscD, (pot[0]>>1)+8);
if(!oscD){
oscD2 = cup(oscD2, 32);
if(pot[0] < 1023 && pot[0] > 0){
analogWrite(11, 255*sinA[oscD2]);
}else if(pot[0] < 1){
digitalWrite(11, HIGH);
}else if(pot[0] > 1022){
digitalWrite(11, LOW);
}
}
delayMicroseconds(4);
}
void remoteI0(){
//fixed, if not it will slow down..
OCR0A = 255;
//oscA2;
oscA2 = cup(oscA2 ,(pot[4]>>1)+1);
//tone decay.
tvol += ((pot[1]+200)*0.000005);
tvol = min(tvol, 8);
if(triggerActive){
triggerActive = false;
//rest volume
tvol = 0;
}
oscA++;
oscA %= (pot[2]>>3)+2;
if(oscA){
ta = !ta;
if(ta){
out = (80 >> (byte)tvol);
}else{
out = 0;
}
}
tvol2 = ((1050-pot[3])*0.0008);
out += waveTable[oscA2]*tvol2;
waveTable[oscA2] = out;
analogWrite(9, (byte)(out*0.3));
}
void remoteL0(){
analogWrite(11, ((1023-pot[0])>>2));
delayMicroseconds(20);
}
void arpegiatorI1(){
OCR0A = 255;
oscB = cup(oscB, (pot[4]<<1)+500);
if(!oscB && !externalTrigger || triggerActive){
triggerActive = false;
trigger(2);
tb = true;
//selectpotmeter for next pitch
oscC = cup(oscC, map(pot[0], 0, 1023, 8, 1));
oscD = cup(oscD, map(pot[2], 0, 1023, 8, 1));
//reset to start volume.
tvol = oscN[oscD]<<2;
}
oscD2 = cup(oscD2, 3);
if(!oscD2){
sendMidi(major[1][oscL[oscC]]+36, (byte)tvol);
//legato
if(tp < (scale[major[1][oscL[oscC]]])){
tp++;
}else if(tp > (scale[major[1][oscL[oscC]]])){
tp--;
}
}
//oscillators timer
oscA = cup(oscA, (tp >> 1));
//filter
analogWrite(11, constrain(((tp-44) << 1), 0, 255));
//decay
tvol-= tvol2;
tvol = max(tvol, 0);
//saw to square so volume stays sort of the same..
out = constrain((oscA<<1), 0, (byte)tvol);
analogWrite(9, out);
}
void arpegiatorL1(){
if(tb){
tb = false;
for(byte i=0; i<8; i++){
//convert to range 0 to 24.
oscL[i] = (((1023-pot[1])*0.0244)*(i+1));
oscL[i] %= 25;
oscN[i] = (((1023-pot[3])*0.0244)*(i+1));
oscN[i] %= 25;
}
}
if(externalTrigger){
tvol2 = pot[4]*0.00015;
}else{
tvol2 = 0.05;
}
delayMicroseconds(50);
}
void remoteI1(){
//fixed, if not it will slow down..
OCR0A = 255;
//oscillators timer
oscA = cup(oscA, tp);
//volume envelope
oscA2 = cup(oscA2, 255);
if(!oscA2){
if(!ta){
cvol++;
cvol = min(cvol, 9);
//analogWrite(11, (cvol << 3));
}
}
analogWrite(9, waveTable[oscA] >> cvol);
}
void remoteL1(){
unsigned int code = 0x00;
//block until start pulse
if(digitalRead(IR_PIN) == LOW){
//http://www.gumbolabs.org/2010/05/29/radioshack-infrared-receiver-arduino/comment-page-1/
while(pulseIn(IR_PIN, LOW) < START_BIT) {}
//read in next 12 bits shifting and masking them into the unsigned int 'code'
//remeber boolean is basically 0 [false] or 1 [true]
for(byte i = 0; i < BITS_PER_MESSAGE; i++) {
code |= (pulseIn(IR_PIN, LOW) > BIT_THRESH) << i;
}
if(code < 138 && code > 127){
oscL[1] = constrain(oscL[1], 96, 128);
tp = scale[code - oscL[1]];
midi.sendNoteOn(midichannel, ((code - oscL[1])+36), 100); //midi
//sendMidi((code - oscL[1])+36, 100); //midi..
oscD = code;
cvol = 2;
}else if(code == 144){ //(PROG) +
oscL[0] += 8;
oscL[0] = min(255, oscL[0]);
analogWrite(11, oscL[0]);
}else if(code == 145){ //(PROG) -
oscL[0] -= 8;
oscL[0] = max(0, oscL[0]);
analogWrite(11, oscL[0]);
}else if(code == 147){ //up (VOL)
oscL[1]++;
oscL[1] = min(128, oscL[1]);
tp = scale[oscD - oscL[1]];
midi.sendNoteOn(midichannel, ((oscD - oscL[1])+36), 100); //midi
cvol = 2;
}else if(code == 146){ //down (VOL)
oscL[1]--;
oscL[1] = max(96, oscL[1]);
tp = scale[oscD - oscL[1]];//oscD holds last note..
midi.sendNoteOn(midichannel, ((oscD - oscL[1])+36), 100); //midi
cvol = 2;
}else if(code == 148){ //hold (MUTE)
ta = !ta;
}else if(code == 149){ //no sound(STANDBY)
cvol = 8;
}else{
oscB = cup(oscB, tp);
if(bitRead(code, (oscB % 8))){
waveTable[oscB] = code % 200;
}else{
waveTable[oscB] = 20;
}
}
}
}
/////////
//other//
/////////
void waveGenartor(int inpA, int inpD){
octaver = cup(octaver, inpD+16);
if(!octaver){
sinAc2 = cup(sinAc2, 32);
}
sinAc = cup(sinAc, 512);
decayA = cup(decayA, (inpA >> 5)+1);
waveTable[sinAc] = (255*sinA[decayA])*sinA[sinAc2];
}
//nice smooth sound!! with droneL0
void waveGenartor4(int inpA, int inpD){
octaver = cup(octaver, inpD);
if(!octaver){
sinAc2 = cup(sinAc2, 32);
}
sinAc = cup(sinAc, inpD>>4); //stange but it sounds nice..
decayA = cup(decayA, (inpA >> 5)+1);
waveTable[sinAc] = (255*sinA[decayA])*sinA[sinAc2];
}
void waveGenartor2(int inpA){
sinAc = cup(sinAc, 512);
decayA = cup(decayA, 32);
waveTable[sinAc] = constrain((inpA*sinA[decayA]), 2, 128);
}
//read pots, 1 at a time
void readAnalogs(){
static byte potc = 0;
potc = cup(potc, 6);
if(reverse){
pot[potc] = analogRead(potc);
}else{
pot[potc] = 1023 - analogRead(potc);
}
}
//send trigger
void trigger(byte inp){
volatile static int tCount = 0;
if(!externalTrigger){
tCount = cup(tCount, inp);
digitalWrite(3, tCount);
digitalWrite(4, tCount);
}
}
void triggerNormal(){
if(inLoop){
//set external trigger to true if there is a trigger signal..
externalTrigger = true;
//set trigger to active, see above
triggerActive = true;
}
}
void triggerOut(){
volatile static boolean triggerSignal = 1;
if(triggerSignal){
triggerNormal();
}
triggerSignal = !triggerSignal;
digitalWrite(3, triggerSignal);
digitalWrite(4, triggerSignal);
}
void resetWavetable(){
for(int i=0; i<512; i++){
waveTable[i] = 0;
}
}
void sendMidi(byte noteIn, byte volume){
static int noteHolder;
if(noteIn != noteHolder){
midi.sendNoteOff(midichannel, noteHolder, 0);
noteHolder = noteIn;
midi.sendNoteOn(midichannel, noteIn, volume);
}
}
inline static int cup(int a, int b){
a++;
if(a >= b){
a = 0;
}
return a;
}