dinsdag 3 juli 2012

29-06-2012 script updates met Raymond, Mikail en Than

We hebben het script voor het muziek-gedeelte aangepast:
samengevat komt het neer op:
- tempo is per heden in bpm in plaats van in millisecondes per tijdseenheid
- delta-t (duratie van events) is nu in 4e, 8e , 16e etc. noten ipv in millisecondes of aantal tijdseenheden
- note velocity is nu vanaf 1 t/m 127 ipv alleen '1' voor noot aan, '0' voor noot uit
- mogelijkheid om na één array een andere array af te spelen, oftewel na een muziekblokje kan er een volgend muziekblokje worden afgespeeld

De bron-code-wijzigingen zullen we de blog besparen ; )
maar hier een Vader Jacob (gevolgd door een los nootje) in het huidige script :


/*********************************************************
v1.0, 20120526
created by Felix (Donkers Creative Technologies)
http://www.donkersct.nl

Derived from original Sparkfun example, see header below.

Optimized for Arduino SDK v1
- uses the "SoftwareSerial" library
and extended code:
- extra function so you can now play simple MIDI sequences
  with multiple MIDI-channels
 
See following some links for details on the MIDI protocol:
http://www.sonicspot.com/guide/midifiles.html
http://www.midi.org/techspecs/gm1sound.php

**********************************************************
version history
1.0, 20120526,  initial version
*********************************************************/


/* This is the original header for "MusicInstrument_Example"
 2-12-2011
 Spark Fun Electronics 2011
 Nathan Seidle

 This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

 This code works with the VS1053 Breakout Board and controls the VS1053 in what is called Real Time MIDI mode.
 To get the VS1053 into RT MIDI mode, power up the VS1053 breakout board with GPIO0 tied low, GPIO1 tied high.

 I use the NewSoftSerial library to send out the MIDI serial at 31250bps. This allows me to print regular messages
 for debugging to the terminal window. This helped me out a ton.

 5V : VS1053 VCC
 GND : VS1053 GND
 D3 (SoftSerial TX) : VS1053 RX
 D4 : VS1053 RESET

 Attach a headphone breakout board to the VS1053:
 VS1053 LEFT : TSH
 VS1053 RIGHT : RSH
 VS1053 GBUF : GND

 When in the drum bank (0x78), there are not different instruments, only different notes.
 To play the different sounds, select an instrument # like 5, then play notes 27 to 87.

 To play "Sticks" (31):
 talkMIDI(0xB0, 0, 0x79); //Bank select: drums
 talkMIDI(0xC0, 5, 0); //Set instrument number
 //Play note on channel 1 (0x90), some note value (note), middle velocity (60):
 noteOn(0, 31, 60);

*/
int volCounter = 20;
int chan0 = 80;
int chan1 = 80;
int chan2 = 80;
int chan3 = 80;
int theVariableT = 0;

// enable debugging with the Arduino serial monitor
#define Serial_monitor

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code
byte resetMIDI = 4; //Tied to VS1053 Reset line
byte ledPin = 13; //MIDI traffic inidicator

// define MIDI soundbanks
#define SB_GM1         0x00
#define SB_FANCYSOUNDS 0x78
#define SB_MELODIC     0x79

struct t_midiHeader {
  byte soundbank[4];
  byte instrument[4];
  byte volume[4];
  byte pitchShift[4];
  int tempo;
}; // t_midiHeader

// HIER MAAK JE EEN CHANNEL AAN
t_midiHeader JacobHeader = {
 {SB_GM1,SB_GM1,SB_GM1,SB_GM1}, //DIT ZIJN MIDI BOARDS
 {60, 1, 1, 3}, // INSTRUMENT BIJ DESBETREFFENDE CHANNEL
 {chan0, chan1, chan2, chan3}, // VOLUME BIJ CHANNEL
 {0, 0, 0, 0}, // PITCH ? DONT KNOW WTF IT IS
 120 // TEMPO
}; // t_midiHeader

struct t_midiNote {
  int  deltaTime; // deltaTime is in ms wordt berekend aan de hand van de nootduur in beats
  byte channel;   // midi channel for this note
  byte note;      // midi note to be played
  byte noteVelocity;     // 0=off, boven 0=on/velocity
}; // t_midiNote

t_midiNote singleNote;
 
t_midiNote Jacob1[] = {
{ 0, 1, 48, 70},
{ 0, 2, 60, 78},
{ 4, 1, 48, 0},
{ 0, 1, 48, 27},
{ 0, 2, 60, 0},
{ 0, 2, 62, 68},
{ 4, 1, 48, 0},
{ 0, 1, 48, 58},
{ 0, 2, 62, 0},
{ 0, 2, 64, 64},
{ 4, 1, 48, 0},
{ 0, 1, 48, 59},
{ 0, 2, 60, 80},
{ 0, 2, 64, 0},
{ 4, 1, 47, 80},
{ 0, 1, 48, 0},
{ 0, 2, 60, 0},
{ 0, 2, 60, 83},
{ 4, 1, 47, 0},
{ 0, 1, 47, 61},
{ 0, 2, 60, 0},
{ 0, 2, 62, 75},
{ 4, 1, 47, 0},
{ 0, 1, 47, 64},
{ 0, 2, 62, 0},
{ 0, 2, 64, 66},
{ 4, 1, 47, 0},
{ 0, 1, 47, 53},
{ 0, 2, 60, 78},
{ 0, 2, 64, 0},
{ 4, 1, 45, 78},
{ 0, 1, 47, 0},
{ 0, 2, 60, 0},
{ 0, 2, 64, 71},
{ 4, 1, 45, 0},
{ 0, 1, 45, 35},
{ 0, 2, 64, 0},
{ 0, 2, 65, 78},
{ 4, 1, 45, 0},
{ 0, 1, 45, 76},
{ 0, 2, 65, 0},
{ 0, 2, 67, 62},
{ 4, 1, 45, 0},
{ 0, 1, 45, 70},
{ 0, 2, 67, 0},
{ 4, 1, 43, 78},
{ 0, 1, 45, 0},
{ 0, 2, 64, 73},
{ 4, 1, 43, 0},
{ 0, 1, 43, 64},
{ 0, 2, 64, 0},
{ 0, 2, 65, 44},
{ 4, 1, 43, 0},
{ 0, 1, 43, 56},
{ 0, 2, 65, 0},
{ 0, 2, 67, 80},
{ 4, 1, 43, 0},
{ 0, 1, 43, 69},
{ 0, 2, 67, 0},
{ 4, 1, 41, 91},
{ 0, 1, 43, 0},
{ 0, 2, 67, 54},
{ 8, 2, 67, 0},
{ 0, 2, 69, 66},
{ 8, 1, 41, 0},
{ 0, 1, 41, 80},
{ 0, 2, 67, 64},
{ 0, 2, 69, 0},
{ 8, 2, 65, 66},
{ 0, 2, 67, 0},
{ 8, 1, 41, 0},
{ 0, 1, 43, 87},
{ 0, 2, 64, 75},
{ 0, 2, 65, 0},
{ 8, 2, 64, 0},
{ 8, 1, 43, 0},
{ 0, 1, 43, 55},
{ 0, 2, 60, 80},
{ 8, 2, 60, 0},
{ 8, 1, 43, 0},
{ 0, 1, 45, 86},
{ 0, 2, 67, 78},
{ 8, 2, 67, 0},
{ 0, 2, 69, 40},
{ 8, 1, 45, 0},
{ 0, 1, 45, 83},
{ 0, 2, 67, 78},
{ 0, 2, 69, 0},
{ 8, 2, 65, 68},
{ 0, 2, 67, 0},
{ 8, 1, 43, 86},
{ 0, 1, 45, 0},
{ 0, 2, 64, 75},
{ 0, 2, 65, 0},
{ 8, 2, 64, 0},
{ 8, 1, 43, 0},
{ 0, 1, 43, 80},
{ 0, 2, 60, 80},
{ 4, 1, 43, 0},
{ 0, 1, 43, 90},
{ 0, 2, 60, 0},
{ 0, 2, 60, 80},
{ 4, 1, 43, 0},
{ 0, 1, 43, 94},
{ 0, 2, 55, 73},
{ 0, 2, 60, 0},
{ 4, 1, 43, 0},
{ 0, 1, 48, 79},
{ 0, 2, 55, 0},
{ 0, 2, 60, 88},
{ 4, 1, 48, 0},
{ 0, 1, 48, 59},
{ 0, 2, 60, 0},
{ 4, 1, 43, 90},
{ 0, 1, 48, 0},
{ 0, 2, 60, 88},
{ 4, 1, 43, 0},
{ 0, 1, 43, 92},
{ 0, 2, 55, 80},
{ 0, 2, 60, 0},
{ 4, 1, 36, 97},
{ 0, 1, 43, 0},
{ 0, 2, 55, 0},
{ 0, 2, 60, 94},
{ 4, 1, 24, 97},
{ 0, 1, 36, 0},
{ 0, 2, 60, 0},
{ 4, 1, 24, 0},



};

t_midiNote Jacob2[] = {
  // deltatime, channel, note, on/off
  { 1, 0, 48, 40},
  { 1, 0, 48, 0},
};

void setup() {
#ifdef Serial_monitor
  Serial.begin(57600);
#endif

  //Setup soft serial for MIDI control
  mySerial.begin(31250);
 
  //Reset the VS1053
  pinMode(resetMIDI, OUTPUT);
  digitalWrite(resetMIDI, LOW);
  delay(100);
  digitalWrite(resetMIDI, HIGH);
  delay(100);
}



void loop() {
playMidiSequence(&JacobHeader, &Jacob1[0], sizeof(Jacob1) / sizeof(singleNote));
//playMidiSequence(&JacobHeader, &Jacob2[0], sizeof(Jacob2) / sizeof(singleNote));
}

//=================================================================
// demo: playMidiSequence
//=================================================================

void playMidiSequence(struct t_midiHeader *header, struct t_midiNote *sequence, int sequenceSize) {
  int sequencePntr = 0;
  byte pitch = 0;
  byte channel = 0;
  byte noteVelocity = 0;

  // initialize MIDI channels
  for (int i=0; i<16; i++) {
    MIDI_setSoundbank(i, header->soundbank[i]);
    MIDI_setVolume(i, header->volume[i]);
    MIDI_setInstrument(i, header->instrument[i]);
  }

  sequencePntr = 0;
 
  while(sequencePntr < sequenceSize ) {
    pitch = sequence[sequencePntr].note + header->pitchShift[sequence[sequencePntr].channel];
    channel = sequence[sequencePntr].channel;    
    noteVelocity = sequence[sequencePntr].noteVelocity;
   
    if (sequence[sequencePntr].noteVelocity > 0) {
      for (int i=0; i<3; i++) {
        MIDI_setVolume(i,chan0); //(channel, channelVelocity)
      }
      MIDI_noteOn(channel, pitch, noteVelocity);
    }
    else
    MIDI_noteOff(channel, pitch, 60);
    sequencePntr++;
   
    int tempoMs = 60000/header->tempo; // 60 000 = 60sec, headertempo is in ms, uitkomst = bpm
    int wholeNote = tempoMs * 4; // hele noot = 4 * kwart noot
    int delta = sequence[sequencePntr].deltaTime;
   
    if (!delta == 0) { // if delta=0 dan geen delay
      delay(wholeNote/delta); // playbackspeed
    }

  }
} // playMidiSequence

/*********************************************************
Various low level MIDI commands
*********************************************************/

//Send a MIDI note-on message.  Like pressing a piano key
//channel ranges from 0-15
void MIDI_noteOn(byte channel, byte note, byte attack_velocity) {
  talkMIDI( (0x90 | channel), note, attack_velocity);
} // MIDI_noteOn

//Send a MIDI note-off message.  Like releasing a piano key
void MIDI_noteOff(byte channel, byte note, byte release_velocity) {
  talkMIDI( (0x80 | channel), note, release_velocity);
} // MIDI_noteOff

//Send a MIDI set soundbank message
void MIDI_setSoundbank(byte channel, byte soundbank) {
  //0xB0 is channel message, set soundbank
  talkMIDI( (0xb0 | channel), 0x00, soundbank);
} // MIDI_setSoundbank

//Send a MIDI volume message
void MIDI_setVolume(byte channel, byte volume) {
  //0xB0 is channel message, set ch_x volume
  talkMIDI( (0xB0 | channel), 0x07, volume);
} // MIDI_setVolume

//Send a MIDI set instrument message
void MIDI_setInstrument(byte channel, byte instrument) {
  //0xC0 is a 1 data byte command, set ch_x instrument number
  talkMIDI( (0xC0 | channel), instrument, 0);
} // MIDI_setInstrument

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
  digitalWrite(ledPin, HIGH);
  mySerial.write(cmd);
  mySerial.write(data1);

  //Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
  //(sort of: http://253.ccarh.org/handout/midiprotocol/)
  if( (cmd & 0xF0) <= 0xB0)
    mySerial.write(data2);

  digitalWrite(ledPin, LOW);
} // talkMIDI





2 opmerkingen:

  1. Hi,
    kan je mij de latest and the greatest code geven, dan kan ik je wellicht helpen met een aantal verbeteringen, ik programmeer al lang in Arduino, en al erg lang in het algemeen... ;)

    BeantwoordenVerwijderen
  2. Hallo daar,
    zijn jullie nog lekker bezig?

    BeantwoordenVerwijderen