NiCMidi 1.1.0
A MIDI library derived from J.D.Koftinoff jdksmidi
test_advancedsequencer_noinput.cpp

A basic example which plays two times a simple tune, without no input from the user.

/*
* Example file for NiCMidi - A C++ Class Library for MIDI
*
* Copyright (C) 2022 Nicola Cassetta
* https://github.com/ncassetta/NiCMidi
*
* This file is part of NiCMidi.
*
* NiCMidi is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* NiCMidi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with NiCMidi. If not, see <http://www.gnu.org/licenses/>.
*/
/*
A basic example which plays two times a simple tune, without no
input from the user.
*/
#include <string>
#include "../include/advancedsequencer.h"
using namespace std;
// A struct holding data for a note
struct note_data {
unsigned char note;
MIDIClockTime length;
};
// G L O B A L S //
// The default ctor creates an AdvancedSequencer with 17 empty tracks (1 master + 16 channel)
// Data for "Twinkle twinkle", track 1
int track1_len = 14;
note_data track1[] = {
{ 60, 110, 480 }, { 60, 110, 600 }, { 67, 110, 720 }, { 67, 110, 840 }, { 69, 110, 960 }, { 69, 110, 1080 },
{ 67, 230, 1200 }, { 65, 110, 1440 }, { 65, 110, 1560 }, { 64, 110, 1680 }, { 64, 110, 1800 },
{ 62, 110, 1920 }, { 62, 110, 2040 }, { 60, 210, 2160 }
};
// Data for "Twinkle twinkle", track 2
int track2_len = 10;
note_data track2[] = {
{ 48, 210, 480 }, { 48, 210, 720 }, { 53, 110, 960 }, { 53, 110, 1080 }, { 48, 210, 1200 }, { 50, 210, 1440 },
{ 48, 210, 1680 }, { 43, 110, 1920 }, { 43, 110, 2040 }, { 48, 210, 2160 }
};
// Data for "Twinkle twinkle", track 3
int track3_len = 47;
note_data track3[] = {
{ 35, 15, 480 }, { 42, 15, 540 }, { 38, 15, 600 }, { 42, 15, 600 }, { 35, 15, 660 }, { 42, 15, 660 },
{ 35, 15, 720 }, { 42, 15, 720}, { 42, 15, 780 }, { 38, 15, 840 }, { 42, 15, 840}, { 42, 15, 900 },
{ 35, 15, 960 }, { 42, 15, 1020 }, { 38, 15, 1080 }, { 42, 15, 1080 }, { 35, 15, 1140 }, { 42, 15, 1140},
{ 35, 15, 1200 }, { 42, 15, 1200}, { 42, 15, 1260 }, { 38, 15, 1320 }, { 42, 15, 1320 }, { 46, 15, 1380 },
{ 35, 15, 1440 }, { 42, 15, 1500 }, { 38, 15, 1560 }, { 42, 15, 1560 }, { 35, 15, 1620 }, { 42, 15, 1620 },
{ 35, 15, 1680 }, { 42, 15, 1680 }, { 42, 15, 1740 }, { 38, 15, 1800 }, { 42, 15, 1800 }, { 42, 15, 1860 },
{ 35, 15, 1920 }, { 42, 15, 1980 }, { 38, 15, 2040 }, { 42, 15, 2040 }, { 35, 15, 2100 }, { 42, 15, 2100 },
{ 35, 15, 2160 }, { 42, 15, 2160 }, { 42, 15, 2220 }, { 35, 15, 2280 }, { 49, 240, 2280 }
};
// M A I N //
int main( int argc, char **argv ) {
// gets the address of the sequencer MIDIMultiTrack, so we can edit it
MIDIMultiTrack* tracks = sequencer.GetMultiTrack();
MIDITrack* trk;
// the constructor creates an undefined (NoOp) message with time 0
// now trk points to the master track (track 0 of the multitrack)
trk = tracks->GetTrack(0);
msg.SetTimeSig(4, 4); // remember that the message time is 0
trk->InsertEvent(msg); // inserts the time signature (4/4)
msg.SetKeySig(0, 0);
trk->InsertEvent(msg); // inserts the key signature (CM)
msg.SetTempo(100.0);
trk->InsertEvent(msg); // inserts the tempo
// now trk points to track 1, we'll use it for MIDI channel 1
trk = tracks->GetTrack(1);
unsigned char channel = 0; // MIDI channel 1
msg.SetProgramChange(channel, 11);
trk->InsertEvent(msg); // inserts the program change at time 0
msg.SetVolumeChange(channel, 110);
trk->InsertEvent(msg); // inserts the track volume
// and now inserts all the notes, taking them from our track1[] array
for(int i = 0; i < track1_len; i++) {
msg.SetNoteOn(channel, track1[i].note, 100);
msg.SetTime(track1[i].time);
trk->InsertNote(msg, track1[i].length);
}
// When you edit the AdvancedSequencer multitrack you must update the
// sequencer parameters before playing: this does the job
sequencer.UpdateStatus();
// now we can play track 1 only
cout << "Playing track 1 ..." << endl;
sequencer.Play();
while (sequencer.IsPlaying())
cout << "The sequencer finished" << endl;
// now do the same for track 2 (bass, channel 2)
trk = tracks->GetTrack(2);
channel = 1;
msg.Clear(); // resets the message
msg.SetProgramChange(channel, 33);
trk->InsertEvent(msg);
msg.SetVolumeChange(channel, 90);
trk->InsertEvent(msg);
for(int i = 0; i < track2_len; i++) {
msg.SetNoteOn(channel, track2[i].note, 100);
msg.SetTime(track2[i].time);
trk->InsertNote(msg, track2[i].length);
}
// ... and 3 (percussion, channel 10)
trk = tracks->GetTrack(3);
channel = 9;
msg.Clear();
//msg.SetProgramChange(channel, 33); // uncomment these if your device doesn't sets
//trk->InsertEvent(msg); // automatically the drums on channel 10
msg.SetVolumeChange(channel, 120);
trk->InsertEvent(msg);
for(int i = 0; i < track3_len; i++) {
msg.SetNoteOn(channel, track3[i].note, 100);
msg.SetTime(track3[i].time);
trk->InsertNote(msg, track3[i].length);
}
sequencer.UpdateStatus();
sequencer.GoToZero();
cout << "Playing 3 tracks ..." << endl;
sequencer.Play();
while (sequencer.IsPlaying())
cout << "The sequencer finished" << endl;;
return EXIT_SUCCESS;
}
An enhanced MIDISequencer, able to directly load and play MIDI files and many more.
Definition: advancedsequencer.h:93
virtual void GoToZero()
Sets the current time to the beginning of the song.
Definition: advancedsequencer.h:255
virtual void UpdateStatus()
This should be used to update the sequencer internal parameters after editing the multitrack.
void SetVolumeChange(unsigned char chan, unsigned char val)
Makes the message a volume change (control == 0x07) message with given channel and value.
Definition: msg.h:256
void SetTimeSig(unsigned char num, unsigned char den, unsigned char clocks_per_metronome=0, unsigned char num_32_per_quarter=8)
Makes the message a time signature meta-message with given time (numerator and denominator).
void SetTempo(float tempo_bpm)
Makes the message a tempo change meta-message with given tempo (in bpm).
void SetProgramChange(unsigned char chan, unsigned char prog)
Makes the message a program change message with given channel and program.
void SetNoteOn(unsigned char chan, unsigned char note, unsigned char vel)
Makes the message a note on message with given channel, note and velocity.
void SetKeySig(signed char sharp_flats, unsigned char major_minor)
Makes the message a key signature meta-message with given accidents and mode.
Definition: msg.h:327
Holds an array of pointers to MIDITrack objects to be played simultaneously.
Definition: multitrack.h:50
MIDITrack * GetTrack(unsigned int trk_num)
Returns the pointer to the track.
Definition: multitrack.h:79
virtual void Play()
This is an alias of Start().
Definition: sequencer.h:455
MIDIMultiTrack * GetMultiTrack()
Returns a pointer to the internal MIDIMultiTrack.
Definition: sequencer.h:232
bool IsPlaying() const
Returns true if the callback procedure is active.
Definition: tick.h:92
The MIDITimedMessage class inherits from the MIDIMessage and represents a message associated with a s...
Definition: msg.h:382
virtual void Clear()
Resets the message, frees the MIDISystemExclusive pointer and sets the time to 0.
void SetTime(MIDIClockTime t)
Sets the MIDIClockTime associated with the message.
Definition: msg.h:410
static void Wait(unsigned int msecs)
Stops the calling thread for the given number of milliseconds.
Definition: timer.h:105
Manages a std::vector of MIDITimedMessage objects storing MIDI events, with methods for editing them.
Definition: track.h:86
bool InsertEvent(const MIDITimedMessage &msg, tInsMode mode=INSMODE_DEFAULT)
Inserts a single event into the track.
bool InsertNote(const MIDITimedMessage &msg, MIDIClockTime len, tInsMode mode=INSMODE_DEFAULT)
Inserts a Note On and a Note Off event into the track.
unsigned long MIDIClockTime
The type of a variable which can hold a time in MIDI ticks.
Definition: midi.h:40