Browse Source

Integrated base2.0, made dead simple visualizer, fixed MidiNote

master
Macoy Madson 5 years ago
parent
commit
b42892813f
  1. 3
      .gitmodules
  2. 15
      Jamfile
  3. 2
      Jamrules
  4. 3
      ThirdParty/Jamfile
  5. 1
      ThirdParty/base2.0
  6. 48
      src/Main.cpp
  7. 42
      src/Midi.cpp
  8. 44
      src/Midi.hpp
  9. 85
      src/SongState.cpp
  10. 33
      src/SongState.hpp
  11. 16
      src/Visualizers/ColorBlocks.cpp
  12. 6
      src/Visualizers/ColorBlocks.hpp

3
.gitmodules

@ -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

15
Jamfile

@ -7,20 +7,19 @@ if $(WINDOWS)
SUFEXE = .exe ;
}
Library libRtMidi : #ThirdParty/rtmidi/midiprobe.cpp
ThirdParty/rtmidi/RtMidi.cpp ;
Library libRtMidi : ThirdParty/rtmidi/RtMidi.cpp ;
MakeLocate libRtMidi.a : lib ;
LinkLibraries liveMusicMachine : libRtMidi ;
LinkLibraries liveMusicMachine : libRtMidi libBase20 ;
Main liveMusicMachine : src/Main.cpp
src/Midi.cpp ;
src/Midi.cpp
src/SongState.cpp
src/Visualizers/ColorBlocks.cpp ;
MakeLocate liveMusicMachine : bin ;
#LinkLibraries liveMusicMachine : libBase20 ;
#
#if $(WINDOWS)
#{
# MakeLocate liveMusicMachine.exe : windowsBin ;
@ -29,5 +28,5 @@ MakeLocate liveMusicMachine : bin ;
#{
# MakeLocate liveMusicMachine : bin ;
#}
#
#SubInclude . libs ;
SubInclude . ThirdParty ;

2
Jamrules

@ -77,7 +77,7 @@ else
OPTIM = -O0 ;
#HDRS = libs/base2.0 ;
HDRS = ThirdParty/rtmidi ;
HDRS = ThirdParty/rtmidi ThirdParty/base2.0 src ;
# Some helpful Jam commands

3
ThirdParty/Jamfile

@ -0,0 +1,3 @@
SubDir . ThirdParty ;
SubInclude . ThirdParty base2.0 ;

1
ThirdParty/base2.0

@ -0,0 +1 @@
Subproject commit 922929ff5678416d4261cc926226c88f6df3816c

48
src/Main.cpp

@ -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;
}

42
src/Midi.cpp

@ -1,5 +1,7 @@
#include "RtMidi.h"
#include "Midi.hpp"
#include <signal.h>
#include <cstdlib>
#include <iostream>
@ -56,44 +58,6 @@ void RtMidiDemoListen()
return;
}
/* 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
{
NoteOn = 8,
NoteOff = 9,
Aftertouch = 0xA,
ControlChange = 0xB,
ProgramChange = 0xC,
ChannelAftertouch = 0xD,
PitchWheel = 0xE,
};
struct MidiNoteOn;
struct MidiCommand
{
unsigned char channel : 4;
MidiCommandType command : 4;
void Print();
};
struct MidiNote
{
unsigned char velocity : 8;
unsigned char note : 8;
MidiCommand status;
void Print();
};
void MidiNote::Print()
{
std::cout << (int)note << " (" << (int)velocity << ")";
@ -171,7 +135,7 @@ void TestRtMidi()
// From demo
{
std::vector<unsigned char> message;
int nBytes, i;
int nBytes;
double stamp;
// Install an interrupt handler function.
done = false;

44
src/Midi.hpp

@ -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();

85
src/SongState.cpp

@ -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;
}
}
}
}

33
src/SongState.hpp

@ -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();
};

16
src/Visualizers/ColorBlocks.cpp

@ -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);
}

6
src/Visualizers/ColorBlocks.hpp

@ -0,0 +1,6 @@
#pragma once
#include "graphics/graphics.hpp"
#include "SongState.hpp"
void Visualization_ColorBlocksUpdate(window& win, SongState& song);
Loading…
Cancel
Save