
12 changed files with 248 additions and 50 deletions
@ -1,3 +1,6 @@ |
|||
[submodule "ThirdParty/rtmidi"] |
|||
path = ThirdParty/rtmidi |
|||
url = https://github.com/thestk/rtmidi |
|||
[submodule "ThirdParty/base2.0"] |
|||
path = ThirdParty/base2.0 |
|||
url = https://github.com/makuto/base2.0 |
|||
|
@ -0,0 +1,3 @@ |
|||
SubDir . ThirdParty ; |
|||
|
|||
SubInclude . ThirdParty base2.0 ; |
@ -1,10 +1,54 @@ |
|||
#include <iostream> |
|||
|
|||
#include "graphics/graphics.hpp" |
|||
#include "input/input.hpp" |
|||
|
|||
#include "Midi.hpp" |
|||
#include "SongState.hpp" |
|||
|
|||
#include "Visualizers/ColorBlocks.hpp" |
|||
|
|||
int WindowWidth = 1200; |
|||
int WindowHeight = 700; |
|||
|
|||
void windowResizeCB(float width, float height) |
|||
{ |
|||
WindowWidth = width; |
|||
WindowHeight = height; |
|||
// RecalculateDimensions();
|
|||
} |
|||
|
|||
window win(WindowWidth, WindowHeight, "Live Music Machine", &windowResizeCB); |
|||
inputManager inp(&win); |
|||
|
|||
#define WIN_BACKGROUND_COLOR 34, 34, 34, 255 |
|||
|
|||
void initializeWindow(window& win) |
|||
{ |
|||
win.setBackgroundColor(WIN_BACKGROUND_COLOR); |
|||
|
|||
// shouldClose manages some state
|
|||
win.shouldClose(); |
|||
win.update(); |
|||
|
|||
win.shouldClear(true); |
|||
win.getBase()->setVerticalSyncEnabled(true); |
|||
win.getBase()->setFramerateLimit(60); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
std::cout << "Hello, world!\n"; |
|||
TestRtMidi(); |
|||
initializeWindow(win); |
|||
|
|||
SongState song; |
|||
|
|||
while (!win.shouldClose() && !inp.isPressed(inputCode::Space)) |
|||
{ |
|||
song.Update(); |
|||
|
|||
Visualization_ColorBlocksUpdate(win, song); |
|||
|
|||
win.update(); |
|||
} |
|||
return 0; |
|||
} |
|||
|
@ -1,3 +1,47 @@ |
|||
#pragma once |
|||
|
|||
/* Midi Commands
|
|||
From http://www.songstuff.com/recording/article/midi_message_format/
|
|||
Note Off 8n Note Number Velocity |
|||
Note On 9n Note Number Velocity |
|||
Polyphonic Aftertouch An Note Number Pressure |
|||
Control Change Bn Controller Number Data |
|||
Program Change Cn Program Number Unused |
|||
Channel Aftertouch Dn Pressure Unused |
|||
Pitch Wheel En LSB MSB |
|||
*/ |
|||
enum class MidiCommandType : unsigned char |
|||
{ |
|||
NoteOff = 8, |
|||
NoteOn = 9, |
|||
Aftertouch = 0xA, |
|||
ControlChange = 0xB, |
|||
ProgramChange = 0xC, |
|||
ChannelAftertouch = 0xD, |
|||
PitchWheel = 0xE, |
|||
}; |
|||
|
|||
typedef unsigned char Channel; |
|||
typedef unsigned char Note; |
|||
typedef unsigned char Velocity; |
|||
|
|||
struct MidiCommand |
|||
{ |
|||
// Do NOT reorder these
|
|||
Channel channel : 4; |
|||
MidiCommandType command : 4; |
|||
|
|||
void Print(); |
|||
}; |
|||
|
|||
struct MidiNote |
|||
{ |
|||
// Do NOT reorder these
|
|||
MidiCommand status; |
|||
Note note : 8; |
|||
Velocity velocity : 8; |
|||
|
|||
void Print(); |
|||
}; |
|||
|
|||
void TestRtMidi(); |
|||
|
@ -0,0 +1,85 @@ |
|||
#include "SongState.hpp" |
|||
|
|||
SongState::SongState() |
|||
{ |
|||
// Open MIDI port
|
|||
{ |
|||
unsigned int numPorts = MidiIn.getPortCount(); |
|||
if (!numPorts) |
|||
{ |
|||
std::cout << "No MIDI ports available\n"; |
|||
return; |
|||
} |
|||
std::cout << numPorts << " MIDI ports available\n"; |
|||
|
|||
MidiIn.openPort(1); |
|||
} |
|||
} |
|||
|
|||
// TODO: Just make this a vector with 16 things already? This will be called a lot
|
|||
SongTrack& SongState::GetTrack(Channel channel) |
|||
{ |
|||
return Tracks[channel]; |
|||
} |
|||
|
|||
void SongState::SetNoteOn(MidiNote* noteMessage) |
|||
{ |
|||
SongTrack& track = GetTrack(noteMessage->status.channel); |
|||
|
|||
track.notesPlaying[noteMessage->note] = noteMessage->velocity; |
|||
} |
|||
|
|||
void SongState::SetNoteOff(MidiNote* noteMessage) |
|||
{ |
|||
SongTrack& track = GetTrack(noteMessage->status.channel); |
|||
|
|||
NoteVelocityMap::iterator findIt = track.notesPlaying.find(noteMessage->note); |
|||
if (findIt != track.notesPlaying.end()) |
|||
{ |
|||
track.notesPlaying.erase(findIt); |
|||
} |
|||
} |
|||
|
|||
void SongState::Update() |
|||
{ |
|||
// Get MIDI messages
|
|||
while (true) |
|||
{ |
|||
std::vector<unsigned char> message; |
|||
int nBytes; |
|||
double stamp; |
|||
stamp = MidiIn.getMessage(&message); |
|||
if (message.empty()) |
|||
break; |
|||
|
|||
nBytes = message.size(); |
|||
if (nBytes && message.size() == 3) |
|||
{ |
|||
MidiCommand* command = reinterpret_cast<MidiCommand*>(&message[0]); |
|||
command->Print(); |
|||
|
|||
switch (command->command) |
|||
{ |
|||
case MidiCommandType::NoteOn: |
|||
{ |
|||
MidiNote* noteOn = reinterpret_cast<MidiNote*>(command); |
|||
SetNoteOn(noteOn); |
|||
break; |
|||
} |
|||
case MidiCommandType::NoteOff: |
|||
{ |
|||
MidiNote* noteOff = reinterpret_cast<MidiNote*>(command); |
|||
SetNoteOff(noteOff); |
|||
break; |
|||
} |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
if (nBytes > 0) |
|||
{ |
|||
std::cout << "stamp = " << stamp << std::endl; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,33 @@ |
|||
#pragma once |
|||
|
|||
#include <map> |
|||
|
|||
#include "RtMidi.h" |
|||
|
|||
#include "Midi.hpp" |
|||
|
|||
typedef std::map<Note, Velocity> NoteVelocityMap; |
|||
|
|||
struct SongTrack |
|||
{ |
|||
Channel channel; |
|||
|
|||
NoteVelocityMap notesPlaying; |
|||
}; |
|||
|
|||
class SongState |
|||
{ |
|||
RtMidiIn MidiIn; |
|||
|
|||
void SetNoteOn(MidiNote* noteMessage); |
|||
void SetNoteOff(MidiNote* noteMessage); |
|||
|
|||
public: |
|||
SongTrack Tracks[16]; |
|||
SongTrack& GetTrack(Channel channel); |
|||
|
|||
SongState(); |
|||
~SongState() = default; |
|||
|
|||
void Update(); |
|||
}; |
@ -0,0 +1,16 @@ |
|||
#include "ColorBlocks.hpp" |
|||
|
|||
void Visualization_ColorBlocksUpdate(window& win, SongState& song) |
|||
{ |
|||
SongTrack& track1 = song.GetTrack(0); |
|||
|
|||
// std::cout << track1.notesPlaying.size() << " notes playing\n";
|
|||
|
|||
if (!track1.notesPlaying.empty()) |
|||
{ |
|||
std::cout << "Played a ntoe\n"; |
|||
win.setBackgroundColor(155, 0, 122, 255); |
|||
} |
|||
else |
|||
win.setBackgroundColor(155, 155, 0, 255); |
|||
} |
@ -0,0 +1,6 @@ |
|||
#pragma once |
|||
|
|||
#include "graphics/graphics.hpp" |
|||
#include "SongState.hpp" |
|||
|
|||
void Visualization_ColorBlocksUpdate(window& win, SongState& song); |
Loading…
Reference in new issue