//
// SoftFluxaSynthSMF.pde: Simple player for byte code files which can be
// generated from MIDI format 0 or 1 files with
// midi2fluxama.pl
//
// Copyrights:
// Copyright (C) 2012 Holger Wirtz dcoredump@gmail.com
//
// This program may be modified and distributed under the
// terms of the GNU General Public License v3. You should have received
// a copy of the GNU General Public License along with this
// program; if not, write to the Free Software Foundation, Inc.
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// USE THIS PROGRAM AT YOUR OWN RISK!
//
// This program code uses "Fluxamasynth_NSS.h" which ca be found at
// http://wiki.moderndevice.com/uploads/MD/Fluxamasynth.zip
//
// The code is testet with Arduino-0.22 but should be easy
// portable to Arduino-1.0.
//
// PREREQUIREMENTS
// You also need the following libraries:
// NewSoftSerial.h NewSoftSerial | Arduiniana
// Flash.h MsTimer2 and FlexiTimer2 Arduino Libraries, Run a Function At Regular Intervals
// FlexiTimer2.h Flash | Arduiniana
//
// See http://arduino.cc where to get the libraries and how to install them.
//
// If someone has MIDI data which sounds amazing and is licensed "free" please
// drop me the MIDI oder header file for including in this distribution.
//
#include <Fluxamasynth_NSS.h>
#include <NewSoftSerial.h> // for software serial (using pin 4)
#include <Flash.h> // needed for storing the song data in PROG_MEM
#include <FlexiTimer2.h> // for correct, interrupt based timing
#include "data.h" // this is the file with the data generated by
// midi2fluxama.pl
#define MASTER_VOL_MAX 100 // the maximum volume
Fluxamasynth synth; :Pthis says fluxamasynth does not name type
unsigned int sp; // the song pointer
unsigned long tempo=500000L;
const int events=midi_data.count();
void setup()
{
synth.midiReset();
synth.setMasterVolume(MASTER_VOL_MAX);
event();
}
void loop()
{
;
}
void event()
{
unsigned long tmp_ulong=0UL;
unsigned int tmp_uint=0,bend=0,wait=0,tmp_sp=0;
byte i=0;
// save the actual song pointer
tmp_sp=sp;
if(sp<events)
{
// special handling of command 7 (delay)
if((midi_data[sp+1]&0x0f)==7)
{
// for delaying next event >255 ticks
for(i=0;i<2;i++)
{
tmp_uint=(unsigned int)midi_data[sp+i+1];
wait+=tmp_uint<<((1-i)*8);
}
sp+=4;
}
if(midi_data[tmp_sp]+wait>0)
{
// timer for the next event
FlexiTimer2::set((((float)tempo/1000)*(((float)midi_data[tmp_sp]+wait)/ppqn)),event);
FlexiTimer2::start();
}
// check the type of event
switch(midi_data[sp+1]&0x0f)
{
case 0: // NoteOn
synth.noteOn(midi_data[sp+1]>>4,midi_data[sp+2],midi_data[sp+3]);
sp+=4;
break;
case 1: // NoteOff
synth.noteOff(midi_data[sp+1]>>4,midi_data[sp+2]);
sp+=3;
break;
case 2: // Controller
synth.setChannelController(midi_data[sp+1]>>4, midi_data[sp+2],midi_data[sp+3]);
sp+=4;
break;
case 3: // PitchBend
for(i=0;i<2;i++)
{
tmp_uint=(unsigned int)midi_data[sp+i+1];
bend+=tmp_uint<<((1-i)*8);
}
synth.pitchBend(midi_data[sp+1]>>4, bend);
sp+=4;
break;
case 4: // ProgramChange
synth.programChange(0,midi_data[sp+1]>>4, midi_data[sp+2]);
sp+=3;
break;
case 5: // Aftertouch
synth.setChannelAftertouch(midi_data[sp+1]>>4, midi_data[sp+2]);
sp+=3;
break;
case 6: // Tempo
tempo=0UL;
for(i=0;i<4;i++)
{
tmp_ulong=(unsigned long)midi_data[sp+i+2];
tempo+=tmp_ulong<<((3-i)*8);
}
sp+=6;
break;
}
if(midi_data[tmp_sp]==0)
event();
}
else
{
// after the end of the song reset the Fluxamasynth
synth.midiReset();
FlexiTimer2::set(5000,event);
FlexiTimer2::start();
return;
}
}