prelim midi controller
This commit is contained in:
78
src/MidiController.cpp
Normal file
78
src/MidiController.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
#include "MidiController.h"
|
||||
#include <iostream>
|
||||
|
||||
MidiController::MidiController(NoteQueue& queue) : noteQueue_(queue) {
|
||||
try {
|
||||
midiIn_ = std::make_unique<RtMidiIn>();
|
||||
midiIn_->ignoreTypes(false, false, false);
|
||||
} catch (RtMidiError& e) {
|
||||
std::cerr << "RtMidi init failed: " << e.getMessage() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
MidiController::~MidiController() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool MidiController::openDefaultPort() {
|
||||
if (!midiIn_) return false;
|
||||
if (midiIn_->getPortCount() == 0) {
|
||||
std::cerr << "No MIDI input ports available\n";
|
||||
return false;
|
||||
}
|
||||
return openPort(0);
|
||||
}
|
||||
|
||||
bool MidiController::openPort(unsigned int index) {
|
||||
if (!midiIn_) return false;
|
||||
|
||||
try {
|
||||
midiIn_->openPort(index);
|
||||
midiIn_->setCallback(&MidiController::midiCallback, this);
|
||||
std::cout << "Opened MIDI port: "
|
||||
<< midiIn_->getPortName(index) << "\n";
|
||||
return true;
|
||||
} catch (RtMidiError& e) {
|
||||
std::cerr << e.getMessage() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MidiController::close() {
|
||||
if (midiIn_ && midiIn_->isPortOpen()) {
|
||||
midiIn_->closePort();
|
||||
}
|
||||
}
|
||||
|
||||
void MidiController::midiCallback(double /*deltaTime*/, std::vector<unsigned char>* message, void* userData) {
|
||||
auto* self = static_cast<MidiController*>(userData);
|
||||
if (!message || message->empty()) return;
|
||||
self->handleMessage(*message);
|
||||
}
|
||||
|
||||
void MidiController::handleMessage(const std::vector<unsigned char>& msg) {
|
||||
unsigned char status = msg[0] & 0xF0;
|
||||
unsigned char note = msg.size() > 1 ? msg[1] : 0;
|
||||
unsigned char vel = msg.size() > 2 ? msg[2] : 0;
|
||||
|
||||
// Note On (velocity > 0)
|
||||
if (status == 0x90 && vel > 0) {
|
||||
noteQueue_.push({
|
||||
NoteEventType::NoteOn,
|
||||
static_cast<uint8_t>(note),
|
||||
vel / 127.0f
|
||||
});
|
||||
}
|
||||
// Note Off (or Note On with velocity 0)
|
||||
else if (status == 0x80 || (status == 0x90 && vel == 0)) {
|
||||
noteQueue_.push({
|
||||
NoteEventType::NoteOff,
|
||||
static_cast<uint8_t>(note),
|
||||
0.0f
|
||||
});
|
||||
}
|
||||
|
||||
// to have a peak :)
|
||||
std::cout << msg[0] << std::endl;
|
||||
}
|
||||
28
src/MidiController.h
Normal file
28
src/MidiController.h
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <RtMidi.h>
|
||||
#include <memory>
|
||||
#include "NoteQueue.h"
|
||||
|
||||
class MidiController {
|
||||
public:
|
||||
explicit MidiController(NoteQueue& queue);
|
||||
~MidiController();
|
||||
|
||||
bool openDefaultPort();
|
||||
bool openPort(unsigned int index);
|
||||
void close();
|
||||
|
||||
private:
|
||||
static void midiCallback(
|
||||
double deltaTime,
|
||||
std::vector<unsigned char>* message,
|
||||
void* userData
|
||||
);
|
||||
|
||||
void handleMessage(const std::vector<unsigned char>& msg);
|
||||
|
||||
std::unique_ptr<RtMidiIn> midiIn_;
|
||||
NoteQueue& noteQueue_;
|
||||
};
|
||||
@@ -9,7 +9,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui_(new Ui::MainWindow),
|
||||
audio_(new AudioEngine()),
|
||||
keyboard_(audio_->noteQueue()) {
|
||||
keyboard_(audio_->noteQueue()),
|
||||
midi_(audio_->noteQueue()) {
|
||||
|
||||
// initialize ui
|
||||
ui_->setupUi(this);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "../synth/AudioEngine.h"
|
||||
#include "../MidiController.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class MainWindow; }
|
||||
@@ -30,5 +31,6 @@ private:
|
||||
|
||||
AudioEngine* audio_ = nullptr;
|
||||
KeyboardController keyboard_;
|
||||
MidiController midi_;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user