Anklang-0.3.0.dev956+gd75ac925 anklang-0.3.0.dev956+gd75ac925
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#pragma once
3
4#include <ase/memory.hh>
5#include <ase/queuemux.hh>
6#include <ase/mathutils.hh>
7
8namespace Ase {
9
10// == Forward Declarations ==
11enum class MusicalTuning : uint8;
12
14enum class MidiEventType : uint8_t {
15 PARAM_VALUE = 0x70,
16 NOTE_OFF = 0x80,
17 NOTE_ON = 0x90,
18 AFTERTOUCH = 0xA0,
19 CONTROL_CHANGE = 0xB0,
20 PROGRAM_CHANGE = 0xC0,
21 CHANNEL_PRESSURE = 0xD0,
22 PITCH_BEND = 0xE0,
23 SYSEX = 0xF0,
24};
25
27enum class MidiMessage : int32_t {
28 NONE = 0,
29 ALL_SOUND_OFF = 120,
30 RESET_ALL_CONTROLLERS = 121,
31 LOCAL_CONTROL = 122,
32 ALL_NOTES_OFF = 123,
33 OMNI_MODE_OFF = 124,
34 OMNI_MODE_ON = 125,
35 MONO_MODE_ON = 126,
36 POLY_MODE_ON = 127,
37 PARAM_VALUE = 0x70,
38 NOTE_OFF = 0x80,
39 NOTE_ON = 0x90,
40 AFTERTOUCH = 0xA0,
41 CONTROL_CHANGE = 0xB0,
42 PROGRAM_CHANGE = 0xC0,
43 CHANNEL_PRESSURE = 0xD0,
44 PITCH_BEND = 0xE0,
45 SYSEX = 0xF0,
46};
47
49struct MidiEvent {
50 using enum MidiEventType;
51 static_assert (AUDIO_BLOCK_MAX_RENDER_SIZE <= 4096); // 0…+4095 fits frame
52 uint frame : 12;
55 union {
56 uint8 key;
57 uint8 fragment;
58 };
59 union {
60 uint length;
61 uint param;
62 uint noteid;
63 };
64 union {
65 char *data;
66 double pvalue;
67 struct {
68 float value;
69 uint cval;
70 };
71 struct {
72 float velocity;
73 float tuning;
74 };
75 };
76 explicit MidiEvent (MidiEventType etype = MidiEventType (0));
77 /*copy*/ MidiEvent (const MidiEvent &other);
78 MidiEvent& operator= (const MidiEvent &other);
79 /*des*/ ~MidiEvent () {}
80 MidiMessage message () const;
81 std::string to_string () const;
82};
83
84MidiEvent make_note_on (uint16 chnl, uint8 mkey, float velo, float tune = 0, uint nid = 0xffffff);
85MidiEvent make_note_off (uint16 chnl, uint8 mkey, float velo, float tune = 0, uint nid = 0xffffff);
86MidiEvent make_aftertouch (uint16 chnl, uint8 mkey, float velo, float tune = 0, uint nid = 0xffffff);
87MidiEvent make_pressure (uint16 chnl, float velo);
88MidiEvent make_control (uint16 chnl, uint prm, float val);
89MidiEvent make_control8 (uint16 chnl, uint prm, uint8 cval);
90MidiEvent make_program (uint16 chnl, uint prgrm);
91MidiEvent make_pitch_bend (uint16 chnl, float val);
92MidiEvent make_param_value (uint param, double pvalue);
93
96 std::vector<MidiEvent> events_; // TODO: use O(1) allocator
97public:
98 explicit MidiEventOutput ();
99 void append (int16_t frame, const MidiEvent &event);
100 const MidiEvent* begin () const noexcept { return &*events_.begin(); }
101 const MidiEvent* end () const noexcept { return &*events_.end(); }
102 size_t size () const noexcept { return events_.size(); }
103 bool empty () const noexcept { return events_.empty(); }
104 void clear () noexcept { events_.clear(); }
105 bool append_unsorted (int16_t frame, const MidiEvent &event);
106 void ensure_order ();
107 int64_t last_frame () const ASE_PURE;
108 size_t capacity () const noexcept { return events_.capacity(); }
109 void reserve (size_t n) { events_.reserve (n); }
111 const& vector () { return events_; }
112};
113
115template<size_t MAXQUEUES>
116class MidiEventReader : QueueMultiplexer<MAXQUEUES,std::vector<MidiEvent>::const_iterator> {
119public:
120 using iterator = typename Base::iterator;
121 using Base::assign;
122 size_t events_pending () const { return this->count_pending(); }
123 iterator begin () { return this->Base::begin(); }
124 iterator end () { return this->Base::end(); }
126 /*ctor*/ MidiEventReader (const VectorArray &midi_event_vector_array = VectorArray());
127};
128
129// == MidiEventReader ==
130template<size_t MAXQUEUES>
131MidiEventReader<MAXQUEUES>::MidiEventReader (const VectorArray &midi_event_vector_array)
132{
133 assign (midi_event_vector_array);
134}
135
136inline int
137QueueMultiplexer_priority (const MidiEvent &e)
138{
139 return e.frame;
140}
141
143struct MidiNote {
144 static constexpr const int NMIN = 0;
145 static constexpr const int NMAX = 131;
146 static constexpr const int NVOID = NMAX + 1;
147 static constexpr const int KAMMER_NOTE = 69; // A' - Kammer Frequency
148 static constexpr const int KAMMER_OCTAVE = +1;
149 static float note_to_freq (MusicalTuning tuning, int note, float kammer_freq);
150};
151
153extern inline float
154MidiNote::note_to_freq (MusicalTuning tuning, int note, float kammer_freq)
155{
156 if (ASE_ISLIKELY (note >= -131) && ASE_ISLIKELY (note <= 131))
157 return semitone_tables_265[uint (tuning)][note - KAMMER_NOTE] * kammer_freq;
158 return 0;
159}
160
161} // Ase
162
A stream of writable MidiEvent structures.
Definition midievent.hh:95
bool append_unsorted(int16_t frame, const MidiEvent &event)
Dangerous! Append a MidiEvent while ignoring sort order, violates constraints.
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:116
#define ASE_ISLIKELY(expr)
Compiler hint to optimize for expr evaluating to true.
Definition cxxaux.hh:44
#define ASE_CLASS_NON_COPYABLE(ClassName)
Delete copy ctor and assignment operator.
Definition cxxaux.hh:110
The Anklang C++ API namespace.
Definition api.hh:8
uint8_t uint8
An 8-bit unsigned integer.
Definition cxxaux.hh:21
const float *const semitone_tables_265[17]
Musical Tuning Tables, to be indexed by MusicalTuning
MidiMessage
Extended type information for MidiEvent.
Definition midievent.hh:27
uint16_t uint16
A 16-bit unsigned integer.
Definition cxxaux.hh:22
MidiEventType
Type of MIDI Events.
Definition midievent.hh:14
@ 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:17
MusicalTuning
Musical tunings, see: http://en.wikipedia.org/wiki/Musical_tuning.
Definition api.hh:82
typedef uint8_t
MidiEvent data structure.
Definition midievent.hh:49
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:54
uint frame
Offset into current block, delayed if negative.
Definition midievent.hh:52
uint channel
0…15 for standard events
Definition midievent.hh:53
Components of a MIDI note.
Definition midievent.hh:143
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:154
Multiplexer to pop from multiple Queues, while preserving priorities.
Definition queuemux.hh:13