This one finally works on all 4 channels, but for the life of me I can't get past using this is a trigger:
if (NotePlayer[CurrentVoice].isPlaying() == false)
//if (millis()>=(lastTime[CurrentVoice]+(settingsGrid[CurrentVoice][Length])))
I'd like to is the bottom line so I can work blank spaces based on settingsGrid[CurrentVoice][Length]
//tonetoy r0001
#include <SoftwareSerial.h>
#include <serLCD.h>
#include <SPI.h>
#include <Tone.h>
//________________________________________________pins!
//spi slave select
const int slaveSelectPin = 53;
const int selectButton = 31;
const int playButton = 30;
// Set pin to the LCD's rxPin
int pin = 18;
serLCD lcd(pin);
int blinker = 40;
//_________________________________________________timing stuff
int menuUpdate = 100;
long menuRefresh = millis();
//last time note played
long lastTime[4] = {0,0,0,0};
//__________________________________________________noteplayer stuff
int voice;
int numVoices = 4;
Tone NotePlayer[4];
int PlayNote;
//noteplayers on/off
boolean active = false;
#define scaleC 0
#define scaleC# 1
#define scaleD 2
#define scaleD# 3
#define scaleE 4
#define scaleF 5
#define scaleF# 6
#define scaleG 7
#define scaleG# 8
#define scaleA 9
#define scaleA# 10
#define scaleB 11
//Scale bitmasks
int modeCode[] = {
2773, 2906, 3670, 2937, 3498, 2457, 2418, 4095, 3289, 3243, 2922, 3449, 2777, 2905, 3170, 2875,
2873, 3162, 2840, 3434, 2742, 3352, 2774, 3413, 3417, 3510, 3305, 3290, 2726, 2642, 3250, 2869, 2730
};
//key offsets
int keyOffset[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
//notes
//NOTES
int Notes[] = {
NOTE_B0, NOTE_C1, NOTE_CS1, NOTE_D1, NOTE_DS1, NOTE_E1, NOTE_F1, NOTE_FS1,
NOTE_G1, NOTE_GS1, NOTE_A1, NOTE_AS1, NOTE_B1, NOTE_C2, NOTE_CS2, NOTE_D2, NOTE_DS2,
NOTE_E2, NOTE_F2, NOTE_FS2, NOTE_G2, NOTE_GS2, NOTE_A2, NOTE_AS2, NOTE_B2, NOTE_C3,
NOTE_CS3, NOTE_D3, NOTE_DS3, NOTE_E3, NOTE_F3, NOTE_FS3, NOTE_G3, NOTE_GS3, NOTE_A3,
NOTE_AS3, NOTE_B3, NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4,
NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5,
NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5, NOTE_C6,
NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6,
NOTE_AS6, NOTE_B6, NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7,
NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7, NOTE_C8, NOTE_CS8, NOTE_D8, NOTE_DS8
};
//______________________________________________________________menus and parameters
int pointer;
// main menu string 10 options
int menuOptions = 10;
int Mode = 0;
int Key = 1;
int Top = 2;
int Bottom = 3;
int Length = 4;
int Odds = 5;
int Attack = 6;
int Decay = 7;
int Sustain = 8;
int Release = 9;
//main menu
char* menuString[]={"Mode ", "Key ", "Top ", "Bottom ", "Length ",
"Odds ", "Attack ","Decay ","Sustain ","Release "};
//mode menu 33 modes
char* modeString[]={"Major ", "Minor ", "Adonai ", "Algerian ",
"Altered ", "Augmented ", "Blues ", "Chromatic ", "Arabic ", "Enigmatic ",
"HalfDim ", "Bebop ", "HarmMaj ", "HarmMin ", "Hirajoshi ", "HuGypsy ",
"HuMinor ", "Insen ", "Iwato ", "Locrian ", "Lydian ", "Hemitonic ",
"Mixolydian ", "NeaMajor ", "NeaMinor ", "Octatonic ", "Persian ", "Phrygian ",
"Prometheus ", "Slendro ", "Tritone ", "UkrDorian ", "WholeTone "};
//Keys submenu 12 keys
char* keyString[]={
"C ", "CS ", "D ", "DS ", "E ", "F ",
"FS ", "G ", "GS ", "A ", "AS ", "B " };
//main parameter holder array
//random start values
int settingsGrid[4][10] = {
{random(33), random(12), (random(4)+4), random(4), random(1023),random(256), random(256),random(256),random(256),random(256)},
{random(33), random(12), (random(4)+4), random(4), random(1023),random(256), random(256),random(256),random(256),random(256)},
{random(33), random(12), (random(4)+4), random(4), random(1023),random(256), random(256),random(256),random(256),random(256)},
{random(33), random(12), (random(4)+4), random(4), random(1023),random(256), random(256),random(256),random(256),random(256)},
};
//_________________________________________________________SETUP
void setup()
{
randomSeed(analogRead(0));
//signal LED
pinMode(40, OUTPUT);
pinMode(playButton, INPUT);
pinMode(selectButton, INPUT);
lcd.clear();
//slave select spi
pinMode (slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
}
//__________________________________________________________LOOP
void loop()
{
digitalWrite(blinker, LOW);
//menu refresh delay timer
if( (long)( millis() - (menuRefresh)+menuUpdate ) >= 0)
{
menuRefresh = millis();
//LCD commands
lcd.setCursor(1, 1);
lcd.print("Voice");
lcd.setCursor(1, 8);
voice = (analogRead(1)/256);
lcd.print((voice+1));
//Line 2 of display
lcd.setCursor(2,1);
pointer = (analogRead(2)/103);
lcd.print(menuString[pointer]);
// Menu scrolling
if (pointer == 0)
{
lcd.print(modeString[settingsGrid[voice][pointer]]);
};
if (pointer == 1)
{
lcd.print(keyString[settingsGrid[voice][pointer]]);
}
if (pointer >= 2)
{
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
}
}
//ENTER DATA
while (digitalRead(selectButton) == HIGH)
{
switch (pointer)
{
case 0:
settingsGrid[voice][pointer] = (analogRead(2)/31.5);
lcd.setCursor(2,6);
lcd.print(modeString[settingsGrid[voice][pointer]]);
break;
case 1:
settingsGrid[voice][pointer] = (analogRead(2)/86);
lcd.setCursor(2,9);
lcd.print(keyString[settingsGrid[voice][pointer]]);
break;
case 2:
settingsGrid[voice][pointer] = (analogRead(2)/128);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
break;
case 3:
settingsGrid[voice][pointer] = (analogRead(2)/128);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
break;
case 4:
settingsGrid[voice][pointer] = (((analogRead(2)/8)*10)+50);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
break;
case 5:
settingsGrid[voice][pointer] = (analogRead(2)/4);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
break;
case 6:
settingsGrid[voice][pointer] = (analogRead(2)/4);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
break;
case 7:
settingsGrid[voice][pointer] = (analogRead(2)/4);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
break;
case 8:
settingsGrid[voice][pointer] = (analogRead(2)/4);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
case 9:
settingsGrid[voice][pointer] = (analogRead(2)/4);
lcd.setCursor(2,9);
lcd.print(settingsGrid[voice][pointer]);
lcd.print(" ");
}
}
//NOTE SELECT, INITIALIZE PLAY, ADSR LOOP?
while (digitalRead(playButton) == HIGH)
{
// digitalWrite(blinker, HIGH);
if (active == false)
{ //INITIALIZE VOX
NotePlayer[0].begin(7);
NotePlayer[1].begin(6);
NotePlayer[2].begin(5);
NotePlayer[3].begin(4);
active = true;
}
{
for (int CurrentVoice = 0; CurrentVoice <= numVoices; CurrentVoice++)
{
if (NotePlayer[CurrentVoice].isPlaying() == false)
//if (millis()>=(lastTime[CurrentVoice]+(settingsGrid[CurrentVoice][Length])))
{
//lastTime[CurrentVoice] = millis();
int ModeSig = settingsGrid[CurrentVoice][Mode];
int SelectNote = random ((((settingsGrid[CurrentVoice][Top])-(settingsGrid[CurrentVoice][Bottom]))*12));
{
if ((bitRead(modeCode[ModeSig], SelectNote)) ==1)
{
PlayNote = (SelectNote + settingsGrid[CurrentVoice][Key] + (settingsGrid[CurrentVoice][Bottom]*12));
}
if (PlayNote > (((settingsGrid[CurrentVoice][Top])-(settingsGrid[CurrentVoice][Bottom]))*12))
// digitalWrite(blinker, HIGH);
{
PlayNote = PlayNote - (((settingsGrid[CurrentVoice][Top])-(settingsGrid[CurrentVoice][Bottom]))*12);
}
}
//digitalWrite(blinker, HIGH);
NotePlayer[CurrentVoice].play(Notes[PlayNote], settingsGrid[CurrentVoice][Length]);
lastTime[CurrentVoice] = millis();
}
}
}
}
}