Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
midievent.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#ifndef __ASE_MIDI_EVENT_HH__
3#define __ASE_MIDI_EVENT_HH__
4
5#include <ase/memory.hh>
6#include <ase/queuemux.hh>
7#include <ase/mathutils.hh>
8
9namespace Ase {
10
11// == Forward Declarations ==
12enum class MusicalTuning : uint8;
13
15enum class MidiEventType : uint8_t {
16 PARAM_VALUE = 0x70,
17 NOTE_OFF = 0x80,
18 NOTE_ON = 0x90,
19 AFTERTOUCH = 0xA0,
20 CONTROL_CHANGE = 0xB0,
21 PROGRAM_CHANGE = 0xC0,
22 CHANNEL_PRESSURE = 0xD0,
23 PITCH_BEND = 0xE0,
24 SYSEX = 0xF0,
25};
26
28enum class MidiMessage : int32_t {
29 NONE = 0,
30 ALL_SOUND_OFF = 120,
31 RESET_ALL_CONTROLLERS = 121,
32 LOCAL_CONTROL = 122,
33 ALL_NOTES_OFF = 123,
34 OMNI_MODE_OFF = 124,
35 OMNI_MODE_ON = 125,
36 MONO_MODE_ON = 126,
37 POLY_MODE_ON = 127,
38 PARAM_VALUE = 0x70,
39 NOTE_OFF = 0x80,
40 NOTE_ON = 0x90,
41 AFTERTOUCH = 0xA0,
42 CONTROL_CHANGE = 0xB0,
43 PROGRAM_CHANGE = 0xC0,
44 CHANNEL_PRESSURE = 0xD0,
45 PITCH_BEND = 0xE0,
46 SYSEX = 0xF0,
47};
48
50struct MidiEvent {
51 using enum MidiEventType;
52 static_assert (AUDIO_BLOCK_MAX_RENDER_SIZE <= 4096); // 0…+4095 fits frame
53 uint frame : 12;
56 union {
57 uint8 key;
58 uint8 fragment;
59 };
60 union {
61 uint length;
62 uint param;
63 uint noteid;
64 };
65 union {
66 char *data;
67 double pvalue;
68 struct {
69 float value;
70 uint cval;
71 };
72 struct {
73 float velocity;
74 float tuning;
75 };
76 };
77 explicit MidiEvent (MidiEventType etype = MidiEventType (0));
78 /*copy*/ MidiEvent (const MidiEvent &other);
79 MidiEvent& operator= (const MidiEvent &other);
80 /*des*/ ~MidiEvent () {}
81 MidiMessage message () const;
82 std::string to_string () const;
83};
84
85MidiEvent make_note_on (uint16 chnl, uint8 mkey, float velo, float tune = 0, uint nid = 0xffffff);
86MidiEvent make_note_off (uint16 chnl, uint8 mkey, float velo, float tune = 0, uint nid = 0xffffff);
87MidiEvent make_aftertouch (uint16 chnl, uint8 mkey, float velo, float tune = 0, uint nid = 0xffffff);
88MidiEvent make_pressure (uint16 chnl, float velo);
89MidiEvent make_control (uint16 chnl, uint prm, float val);
90MidiEvent make_control8 (uint16 chnl, uint prm, uint8 cval);
91MidiEvent make_program (uint16 chnl, uint prgrm);
92MidiEvent make_pitch_bend (uint16 chnl, float val);
93MidiEvent make_param_value (uint param, double pvalue);
94
97 std::vector<MidiEvent> events_; // TODO: use O(1) allocator
98public:
99 explicit MidiEventOutput ();
100 void append (int16_t frame, const MidiEvent &event);
101 const MidiEvent* begin () const noexcept { return &*events_.begin(); }
102 const MidiEvent* end () const noexcept { return &*events_.end(); }
103 size_t size () const noexcept { return events_.size(); }
104 bool empty () const noexcept { return events_.empty(); }
105 void clear () noexcept { events_.clear(); }
106 bool append_unsorted (int16_t frame, const MidiEvent &event);
107 void ensure_order ();
108 int64_t last_frame () const ASE_PURE;
109 size_t capacity () const noexcept { return events_.capacity(); }
110 void reserve (size_t n) { events_.reserve (n); }
112 const& vector () { return events_; }
113};
114
116template<size_t MAXQUEUES>
117class MidiEventReader : QueueMultiplexer<MAXQUEUES,std::vector<MidiEvent>::const_iterator> {
120public:
121 using iterator = typename Base::iterator;
122 using Base::assign;
123 size_t events_pending () const { return this->count_pending(); }
124 iterator begin () { return this->Base::begin(); }
125 iterator end () { return this->Base::end(); }
127 /*ctor*/ MidiEventReader (const VectorArray &midi_event_vector_array = VectorArray());
128};
129
130// == MidiEventReader ==
131template<size_t MAXQUEUES>
132MidiEventReader<MAXQUEUES>::MidiEventReader (const VectorArray &midi_event_vector_array)
133{
134 assign (midi_event_vector_array);
135}
136
137inline int
138QueueMultiplexer_priority (const MidiEvent &e)
139{
140 return e.frame;
141}
142
144struct MidiNote {
145 static constexpr const int NMIN = 0;
146 static constexpr const int NMAX = 131;
147 static constexpr const int NVOID = NMAX + 1;
148 static constexpr const int KAMMER_NOTE = 69; // A' - Kammer Frequency
149 static constexpr const int KAMMER_OCTAVE = +1;
150 static float note_to_freq (MusicalTuning tuning, int note, float kammer_freq);
151};
152
154extern inline float
155MidiNote::note_to_freq (MusicalTuning tuning, int note, float kammer_freq)
156{
157 if (ASE_ISLIKELY (note >= -131) && ASE_ISLIKELY (note <= 131))
158 return semitone_tables_265[uint (tuning)][note - KAMMER_NOTE] * kammer_freq;
159 return 0;
160}
161
162} // Ase
163
164#endif // __ASE_MIDI_EVENT_HH__
A stream of writable MidiEvent structures.
Definition midievent.hh:96
bool append_unsorted(int16_t frame, const MidiEvent &event)
Definition midievent.cc:192
void ensure_order()
Fix event order after append_unsorted() returned true.
Definition midievent.cc:205
int64_t last_frame() const ASE_PURE
Fetch the latest event stamp, can be used to enforce order.
Definition midievent.cc:214
void append(int16_t frame, const MidiEvent &event)
Append an MidiEvent with conscutive frame time stamp.
Definition midievent.cc:183
An in-order MidiEvent reader for multiple MidiEvent sources.
Definition midievent.hh:117
#define ASE_ISLIKELY(expr)
Compiler hint to optimize for expr evaluating to true.
Definition cxxaux.hh:45
#define ASE_CLASS_NON_COPYABLE(ClassName)
Delete copy ctor and assignment operator.
Definition cxxaux.hh:106
The Anklang C++ API namespace.
Definition api.hh:9
uint8_t uint8
An 8-bit unsigned integer.
Definition cxxaux.hh:22
const float *const semitone_tables_265[17]
Musical Tuning Tables, to be indexed by MusicalTuning
MidiMessage
Extended type information for MidiEvent.
Definition midievent.hh:28
uint16_t uint16
A 16-bit unsigned integer.
Definition cxxaux.hh:23
MidiEventType
Type of MIDI Events.
Definition midievent.hh:15
@ NOTE_OFF
Ase internal Parameter update.
@ CONTROL_CHANGE
Control Change.
@ AFTERTOUCH
Key Pressure, polyphonic aftertouch.
@ CHANNEL_PRESSURE
Channel Aftertouch.
uint32_t uint
Provide 'uint' as convenience type.
Definition cxxaux.hh:18
MusicalTuning
Musical tunings, see: http://en.wikipedia.org/wiki/Musical_tuning.
Definition api.hh:83
typedef uint8_t
MidiEvent data structure.
Definition midievent.hh:50
MidiMessage message() const
Determine extended message type an MidiEvent.
Definition midievent.cc:36
MidiEventType type
MidiEvent type, one of the MidiEventType members.
Definition midievent.hh:55
uint frame
Offset into current block, delayed if negative.
Definition midievent.hh:53
uint channel
0…15 for standard events
Definition midievent.hh:54
Components of a MIDI note.
Definition midievent.hh:144
static float note_to_freq(MusicalTuning tuning, int note, float kammer_freq)
Convert MIDI note to Hertz for a MusicalTuning and kammer_freq.
Definition midievent.hh:155