/[svn]/linuxsampler/trunk/src/drivers/midi/VirtualMidiDevice.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/midi/VirtualMidiDevice.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2522 - (show annotations) (download)
Wed Feb 19 19:21:31 2014 UTC (8 years, 11 months ago) by schoenebeck
File size: 6268 byte(s)
- C++11 compliance fixes regarding previous commit.

1 /*
2 Copyright (C) 2008 - 2014 Christian Schoenebeck
3 */
4
5 #include "VirtualMidiDevice.h"
6
7 #include "../../common/global_private.h"
8 #include "../../common/atomic.h"
9 #include "../../common/RingBuffer.h"
10
11 #define MIDI_KEYS 128
12 #define MIDI_CONTROLLERS 128
13
14 // assuming VirtualMidiDevice implementation is only controlled
15 // by mouse (and the user not being Billy the Kid)
16 #define MAX_EVENTS 12
17
18 namespace LinuxSampler {
19
20 struct VirtualMidiDevice::private_data_t {
21 atomic_t notesChanged; // whether some key changed at all
22 atomic_t pNoteChanged[MIDI_KEYS]; // which key(s) changed
23 atomic_t pNoteIsActive[MIDI_KEYS]; // status of each key (either active or inactive)
24 atomic_t pNoteOnVelocity[MIDI_KEYS];
25 atomic_t pNoteOffVelocity[MIDI_KEYS];
26 atomic_t ccsChanged; // whether some controller changed at all
27 atomic_t pCCChanged[MIDI_CONTROLLERS]; // which controller(s) changed
28 atomic_t pCCValue[MIDI_CONTROLLERS]; // current value of each controller
29 RingBuffer<VirtualMidiDevice::event_t,false> events;
30
31 private_data_t() : events(MAX_EVENTS, 0) {}
32 };
33
34 VirtualMidiDevice::VirtualMidiDevice() : p(new private_data_t) {
35 atomic_t zero = ATOMIC_INIT(0);
36 atomic_t defaultVelocity = ATOMIC_INIT(127);
37 atomic_t defaultCCValue = ATOMIC_INIT(0);
38 p->notesChanged = zero;
39 p->ccsChanged = zero;
40 for (int i = 0; i < MIDI_KEYS; i++) {
41 p->pNoteChanged[i] = zero;
42 p->pNoteIsActive[i] = zero;
43 p->pNoteOnVelocity[i] = defaultVelocity;
44 p->pNoteOffVelocity[i] = defaultVelocity;
45 p->pCCChanged[i] = zero;
46 p->pCCValue[i] = defaultCCValue;
47 }
48 }
49
50 VirtualMidiDevice::~VirtualMidiDevice() {
51 delete p;
52 }
53
54 void VirtualMidiDevice::SetMaxEvents(int n) {
55 p->events.resize(n);
56 }
57
58 bool VirtualMidiDevice::SendNoteOnToSampler(uint8_t Key, uint8_t Velocity) {
59 if (Key >= MIDI_KEYS || Velocity > 127) return false;
60 if (Velocity == 0) {
61 return SendNoteOffToSampler(Key, Velocity);
62 }
63 event_t ev = { EVENT_TYPE_NOTEON, Key, Velocity };
64 if (p->events.write_space() <= 0) return false;
65 p->events.push(&ev);
66 return true;
67 }
68
69 bool VirtualMidiDevice::SendNoteOffToSampler(uint8_t Key, uint8_t Velocity) {
70 if (Key >= MIDI_KEYS || Velocity > 127) return false;
71 event_t ev = { EVENT_TYPE_NOTEOFF, Key, Velocity };
72 if (p->events.write_space() <= 0) return false;
73 p->events.push(&ev);
74 return true;
75 }
76
77 bool VirtualMidiDevice::SendCCToSampler(uint8_t Controller, uint8_t Value) {
78 if (Controller >= MIDI_CONTROLLERS || Value > 127) return false;
79 event_t ev = { EVENT_TYPE_CC, Controller, Value };
80 if (p->events.write_space() <= 0) return false;
81 p->events.push(&ev);
82 return true;
83 }
84
85 bool VirtualMidiDevice::SendPitchBendToSampler(int Pitch) {
86 if (Pitch < -8192 || Pitch > 8191) return false;
87 Pitch += 8192;
88 // order: LSB, MSB like it would be in a regular pitch bend MIDI message
89 event_t ev = {
90 EVENT_TYPE_PITCHBEND,
91 static_cast<uint8_t>(Pitch & 0x7f),
92 static_cast<uint8_t>((Pitch >> 7) & 0x7f)
93 };
94 if (p->events.write_space() <= 0) return false;
95 p->events.push(&ev);
96 return true;
97 }
98
99 bool VirtualMidiDevice::SendProgramChangeToSampler(uint8_t Program) {
100 if (Program > 127) return false;
101 event_t ev = { EVENT_TYPE_PROGRAM, Program, 0 };
102 if (p->events.write_space() <= 0) return false;
103 p->events.push(&ev);
104 return true;
105 }
106
107 bool VirtualMidiDevice::GetMidiEventFromDevice(event_t& Event) {
108 return (p->events.pop(&Event) > 0);
109 }
110
111 bool VirtualMidiDevice::NotesChanged() {
112 int c = atomic_read( &p->notesChanged );
113 atomic_sub(c, &p->notesChanged );
114 return c;
115 }
116
117 bool VirtualMidiDevice::ControllersChanged() {
118 int c = atomic_read( &p->ccsChanged );
119 atomic_sub(c, &p->ccsChanged );
120 return c;
121 }
122
123 bool VirtualMidiDevice::NoteChanged(uint8_t Key) {
124 int c = atomic_read( &(p->pNoteChanged)[Key] );
125 atomic_sub(c, &(p->pNoteChanged)[Key] );
126 return c;
127 }
128
129 bool VirtualMidiDevice::ControllerChanged(uint8_t Controller) {
130 int c = atomic_read( &(p->pCCChanged)[Controller] );
131 atomic_sub(c, &(p->pCCChanged)[Controller] );
132 return c;
133 }
134
135 bool VirtualMidiDevice::NoteIsActive(uint8_t Key) {
136 return atomic_read( &(p->pNoteIsActive)[Key] );
137 }
138
139 uint8_t VirtualMidiDevice::NoteOnVelocity(uint8_t Key) {
140 return atomic_read( &(p->pNoteOnVelocity)[Key] );
141 }
142
143 uint8_t VirtualMidiDevice::NoteOffVelocity(uint8_t Key) {
144 return atomic_read( &(p->pNoteOffVelocity)[Key] );
145 }
146
147 uint8_t VirtualMidiDevice::ControllerValue(uint8_t Controller) {
148 return atomic_read( &(p->pCCValue)[Controller] );
149 }
150
151 void VirtualMidiDevice::SendNoteOnToDevice(uint8_t Key, uint8_t Velocity) {
152 if (Key >= MIDI_KEYS) return;
153 if (Velocity == 0) {
154 SendNoteOffToDevice(Key, Velocity);
155 return;
156 }
157 atomic_set( &(p->pNoteOnVelocity)[Key], Velocity );
158 atomic_inc( &(p->pNoteIsActive)[Key] );
159 atomic_inc( &(p->pNoteChanged)[Key] );
160 atomic_inc( &p->notesChanged );
161 }
162
163 void VirtualMidiDevice::SendNoteOffToDevice(uint8_t Key, uint8_t Velocity) {
164 if (Key >= MIDI_KEYS) return;
165 atomic_set( &(p->pNoteOffVelocity)[Key], Velocity );
166 if (atomic_read( &(p->pNoteIsActive)[Key] )) // only decrement if not zero
167 atomic_dec( &(p->pNoteIsActive)[Key] );
168 atomic_inc( &(p->pNoteChanged)[Key] );
169 atomic_inc( &p->notesChanged );
170 }
171
172 void VirtualMidiDevice::SendCCToDevice(uint8_t Controller, uint8_t Value) {
173 if (Controller >= MIDI_CONTROLLERS) return;
174 atomic_set( &(p->pCCValue)[Controller], Value );
175 atomic_inc( &(p->pCCChanged)[Controller] );
176 atomic_inc( &p->ccsChanged );
177 }
178
179 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC