-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMidiToOPL.h
89 lines (80 loc) · 2.31 KB
/
MidiToOPL.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#pragma once
#include "Midi.h"
#include "Note.h"
/*
* MidiToOPL.h
*
* Created on: 21.08.2016
* Author: tly
*/
inline float midiToFreq(int note){
return pow(2,(note-57)/12.0) * 440;
}
inline float pitchBendFreq(float freq,float t,float range) {
return freq * pow(2,range * t / 12);
}
template<typename Serial,typename YM> struct MidiToOpl{
MidiToOpl(Serial& s,YM& ym) : midi(s), ym(ym){}
float pitchBendRange = 2;
void tick(){
midi.eventFunc();
}
void init(){
static MidiToOpl<Serial,YM>* instance = this;
midi.begin();
midi.onKeyPressed = [](uint8_t note,uint8_t velocity){
auto n = instance->noteManager.getNote(note);
int noteIndex = instance->noteManager.addNote(note);
if(n || instance->ym.isKeyOn(noteIndex)){
//note already existed, needs rehit.
instance->ym.keyOff(noteIndex);
}
instance->ym.keyOn(noteIndex,pitchBendFreq(midiToFreq(note),instance->pitchBend,instance->pitchBendRange));
};
midi.onKeyReleased = [](uint8_t note){
if(!instance->sustain){
int noteIndex = instance->noteManager.removeNote(note);
if(noteIndex >= 0 && noteIndex < 9){
instance->ym.keyOff(noteIndex);
}
}else{
if(auto n = instance->noteManager.getNote(note)){
n->mode = SUSTAIN;
}
}
};
midi.onPitchBend = [](uint16_t value){
instance->pitchBend = (value - 8192.0)/8192;
for(uint8_t i = 0; i < 9; i++){
auto& node = instance->noteManager.noteNodes[i];
if(node.noteData.note){
instance->ym.setFrequency(i,pitchBendFreq(midiToFreq(node.noteData.note),instance->pitchBend,instance->pitchBendRange));
}
}
};
midi.onControlChange = [](uint8_t controller,uint8_t value){
if(controller == 64){
if(value > 63){
instance->sustain = true;
}else{
instance->sustain = false;
for(uint8_t i = 0; i < 9; i++){
auto& node = instance->noteManager.noteNodes[i];
if(node.noteData.note && node.noteData.mode == SUSTAIN){
int noteIndex = instance->noteManager.removeNote(node.noteData.note);
if(noteIndex >= 0 && noteIndex < 9){
instance->ym.keyOff(noteIndex);
}
}
}
}
}
};
}
Midi<Serial> midi;
protected:
float pitchBend = 0;
bool sustain = false;
YM& ym;
NoteManager<9> noteManager;
};