I got a gameduino yesterday, and though i would test out the synth engine.
8 voice polyphonic, and each voice can have 8 partials "organ stops" (they are fixed at the moment, ill add some potentiometers to change the sound)
you will need a MIDI input, or change it to receive MIDI from your computer via USB (dont ask how to do that, but i know you can)
//Gameduino has DC on the output. you should put a capacitor on the outputs if your monitoring system is DC coupled.
//Polyphonic gameduino organ 0.00000001
//june 2011 J.Matheson [DeFex][Neutron7]
#include <SPI.h>
#include <GD.h>
#include <MIDI.h> //avaliable from arduino playground
byte vo[] = {
0,0,0,0,0,0,0,0}; //polyphony voice array
byte voFlag[] = {
0,0,0,0,0,0,0,0}; //polyphony active flags
byte voActive; //total of active notes
byte counter1;
byte playNum;
byte vel;
unsigned int MIDItoGDFREQ[] = { //MIDI to frequence x 4 rounded.
33,35,37,39,41,44,46,49,
52,55,58,62,65,69,73,78,
82,87,92,98,104,110,117,123,
131,139,147,156,165,175,185,196,
208,220,233,247,262,277,294,311,
330,349,370,392,415,440,466,494,
523,554,587,622,659,698,740,784,
831,880,932,988,1047,1109,1175,1245,
1319,1397,1480,1568,1661,1760,1865,1976,
2093,2217,2349,2489,2637,2794,2960,3136,
3322,3520,3729,3951,4186,4435,4699,4978,
5274,5588,5920,6272,6645,7040,7459,7902};
struct voice //left from original gameduino sketch, not used except for initialization
{
float f;
float a;
}
voices[16];
void load()
{
byte v;
unsigned int gg = 0;
float sum = 0.0;
for (v = 0; v < 16; v++) {
sum += voices[v].a;
}
float scale = 255.0 / sum;
for (v = 0; v < 16; v++) {
byte a = int(voices[v].a * scale);
GD.voice(v, 0, int(4 * voices[v].f), a, a);
}
}
void note(byte voActive,byte m,byte vnum, byte velo)
{
int offset = vnum<<3; //add 8 to the voice numbers for each polyphonic voice
if (velo > 0){
int level = 32;//this could be dynamically changed by velocity
unsigned int n = MIDItoGDFREQ[m];
unsigned int n2 = n + 2; //slight detuning of some oscillators
GD.voice(offset+0, 0, n, level>>1, level>>1); //mess around with these,
//everything together should not add up to more than 356 / the number of voices playing
GD.voice(offset+1, 0, (n<<1), level>>2, level>>2);
GD.voice(offset+2, 0, (n*3)-4, level>>3, level>>2);
GD.voice(offset+3, 0, (n<<2)-7, level>>2, level>>3);
GD.voice(offset+4, 0, (n*5), level>>5, level>>5);
GD.voice(offset+5, 0, n2, level>>2, level>>2);
GD.voice(offset+6, 0, (n2<<1)+4, level>>1, level>>1);
GD.voice(offset+7, 0, (n2<<1)+9, level>>2, level>>2);
}
else{ //note off
GD.voice(offset+0, 0, 0, 0, 0);
GD.voice(offset+1, 0, 0, 0, 0);
GD.voice(offset+2, 0, 0, 0, 0);
GD.voice(offset+3, 0, 0, 0, 0);
GD.voice(offset+4, 0, 0, 0, 0);
GD.voice(offset+5, 0, 0, 0, 0);
GD.voice(offset+6, 0, 0, 0, 0);
GD.voice(offset+7, 0, 0, 0, 0);
}
}
void setup()
{
int i;
delay(250);
GD.begin();
MIDI.begin(MIDI_CHANNEL_OMNI);
MIDI.setHandleNoteOn(HandleNoteOn); //for the MIDI.h library
MIDI.setHandleNoteOff(HandleNoteOff);
//GD.MODULATOR = 32;
}
void HandleNoteOn(byte channel, byte pitch, byte velocity) {
voActive = 0;
for (counter1 = 0; counter1 < 8; counter1++) { //count through the polyphonic voice array and find an empty slot.
if (voFlag[counter1] == 0){
vo[counter1] = pitch;
voFlag[counter1] = 1;
playNum = counter1;
break;
}
}
for (counter1 = 0; counter1 < 8; counter1++) {
if (voFlag[counter1] == 1){
voActive ++;
}
}
note(voActive,pitch,playNum,velocity);
if (velocity == 0) {
for (counter1 = 0; counter1 < 8; counter1++) {
if (vo[counter1] == pitch){
vo[counter1] = 0;
voFlag[counter1] = 0;
playNum = counter1;
note(voActive,0,playNum,vel);
// This acts as a NoteOff on some controllers
}
}
}
}
void HandleNoteOff(byte channel, byte pitch, byte velocity) {
for (counter1 = 0; counter1 < 8; counter1++) {
if (vo[counter1] == pitch){
vo[counter1] = 0;
voFlag[counter1] = 0;
playNum = counter1;
note(voActive,0,playNum,vel);
// This finds any notes that match the note number
//in the polyphony array and turns them off.
}
}
}
void loop()
{
MIDI.read(); //could put LFOs, modulation, envelopes and stuff in here.
}