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
Hi,
BeantwoordenVerwijderenkan 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... ;)
Hallo daar,
BeantwoordenVerwijderenzijn jullie nog lekker bezig?