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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3018 - (hide annotations) (download)
Wed Oct 19 17:22:28 2016 UTC (7 years, 6 months ago) by schoenebeck
File size: 6594 byte(s)
* Added new C++ API method
  VirtualMidiDevice::SendChannelPressureToSampler().
* Bumped version (2.0.0.svn30).

1 schoenebeck 1659 /*
2 schoenebeck 3018 Copyright (C) 2008 - 2016 Christian Schoenebeck
3 schoenebeck 1659 */
4    
5     #include "VirtualMidiDevice.h"
6    
7     #include "../../common/global_private.h"
8     #include "../../common/atomic.h"
9     #include "../../common/RingBuffer.h"
10    
11 schoenebeck 2025 #define MIDI_KEYS 128
12     #define MIDI_CONTROLLERS 128
13 schoenebeck 1659
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 persson 1896 struct VirtualMidiDevice::private_data_t {
21 schoenebeck 1659 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 schoenebeck 1663 atomic_t pNoteOnVelocity[MIDI_KEYS];
25     atomic_t pNoteOffVelocity[MIDI_KEYS];
26 schoenebeck 2025 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 schoenebeck 1659 RingBuffer<VirtualMidiDevice::event_t,false> events;
30    
31 persson 1896 private_data_t() : events(MAX_EVENTS, 0) {}
32 schoenebeck 1659 };
33    
34 persson 1896 VirtualMidiDevice::VirtualMidiDevice() : p(new private_data_t) {
35 schoenebeck 1659 atomic_t zero = ATOMIC_INIT(0);
36 schoenebeck 1663 atomic_t defaultVelocity = ATOMIC_INIT(127);
37 schoenebeck 2025 atomic_t defaultCCValue = ATOMIC_INIT(0);
38 schoenebeck 1659 p->notesChanged = zero;
39 schoenebeck 2025 p->ccsChanged = zero;
40 schoenebeck 1659 for (int i = 0; i < MIDI_KEYS; i++) {
41     p->pNoteChanged[i] = zero;
42     p->pNoteIsActive[i] = zero;
43 schoenebeck 1663 p->pNoteOnVelocity[i] = defaultVelocity;
44     p->pNoteOffVelocity[i] = defaultVelocity;
45 schoenebeck 2025 p->pCCChanged[i] = zero;
46     p->pCCValue[i] = defaultCCValue;
47 schoenebeck 1659 }
48     }
49    
50     VirtualMidiDevice::~VirtualMidiDevice() {
51 persson 1896 delete p;
52 schoenebeck 1659 }
53 schoenebeck 2384
54     void VirtualMidiDevice::SetMaxEvents(int n) {
55     p->events.resize(n);
56     }
57 schoenebeck 1659
58     bool VirtualMidiDevice::SendNoteOnToSampler(uint8_t Key, uint8_t Velocity) {
59     if (Key >= MIDI_KEYS || Velocity > 127) return false;
60 schoenebeck 2385 if (Velocity == 0) {
61     return SendNoteOffToSampler(Key, Velocity);
62     }
63 schoenebeck 1659 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 schoenebeck 2025
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 schoenebeck 1659
85 schoenebeck 3018 bool VirtualMidiDevice::SendChannelPressureToSampler(uint8_t Pressure) {
86     if (Pressure > 127) return false;
87     event_t ev = { EVENT_TYPE_CHPRESSURE, 128 /*actually ignored by engine*/, Pressure };
88     if (p->events.write_space() <= 0) return false;
89     p->events.push(&ev);
90     return true;
91     }
92    
93 schoenebeck 2521 bool VirtualMidiDevice::SendPitchBendToSampler(int Pitch) {
94     if (Pitch < -8192 || Pitch > 8191) return false;
95     Pitch += 8192;
96     // order: LSB, MSB like it would be in a regular pitch bend MIDI message
97 schoenebeck 2522 event_t ev = {
98     EVENT_TYPE_PITCHBEND,
99     static_cast<uint8_t>(Pitch & 0x7f),
100     static_cast<uint8_t>((Pitch >> 7) & 0x7f)
101     };
102 schoenebeck 2521 if (p->events.write_space() <= 0) return false;
103     p->events.push(&ev);
104     return true;
105     }
106    
107 schoenebeck 2522 bool VirtualMidiDevice::SendProgramChangeToSampler(uint8_t Program) {
108     if (Program > 127) return false;
109 schoenebeck 2521 event_t ev = { EVENT_TYPE_PROGRAM, Program, 0 };
110     if (p->events.write_space() <= 0) return false;
111     p->events.push(&ev);
112     return true;
113     }
114    
115 schoenebeck 1659 bool VirtualMidiDevice::GetMidiEventFromDevice(event_t& Event) {
116     return (p->events.pop(&Event) > 0);
117     }
118    
119     bool VirtualMidiDevice::NotesChanged() {
120     int c = atomic_read( &p->notesChanged );
121     atomic_sub(c, &p->notesChanged );
122     return c;
123     }
124 schoenebeck 2025
125     bool VirtualMidiDevice::ControllersChanged() {
126     int c = atomic_read( &p->ccsChanged );
127     atomic_sub(c, &p->ccsChanged );
128     return c;
129     }
130 schoenebeck 1659
131     bool VirtualMidiDevice::NoteChanged(uint8_t Key) {
132     int c = atomic_read( &(p->pNoteChanged)[Key] );
133     atomic_sub(c, &(p->pNoteChanged)[Key] );
134     return c;
135     }
136 schoenebeck 2025
137     bool VirtualMidiDevice::ControllerChanged(uint8_t Controller) {
138     int c = atomic_read( &(p->pCCChanged)[Controller] );
139     atomic_sub(c, &(p->pCCChanged)[Controller] );
140     return c;
141     }
142 schoenebeck 1659
143     bool VirtualMidiDevice::NoteIsActive(uint8_t Key) {
144     return atomic_read( &(p->pNoteIsActive)[Key] );
145     }
146    
147 schoenebeck 1663 uint8_t VirtualMidiDevice::NoteOnVelocity(uint8_t Key) {
148     return atomic_read( &(p->pNoteOnVelocity)[Key] );
149     }
150    
151     uint8_t VirtualMidiDevice::NoteOffVelocity(uint8_t Key) {
152     return atomic_read( &(p->pNoteOffVelocity)[Key] );
153     }
154 schoenebeck 2025
155     uint8_t VirtualMidiDevice::ControllerValue(uint8_t Controller) {
156     return atomic_read( &(p->pCCValue)[Controller] );
157     }
158 schoenebeck 1663
159     void VirtualMidiDevice::SendNoteOnToDevice(uint8_t Key, uint8_t Velocity) {
160 schoenebeck 1659 if (Key >= MIDI_KEYS) return;
161 schoenebeck 2385 if (Velocity == 0) {
162     SendNoteOffToDevice(Key, Velocity);
163     return;
164     }
165 schoenebeck 1663 atomic_set( &(p->pNoteOnVelocity)[Key], Velocity );
166 schoenebeck 1659 atomic_inc( &(p->pNoteIsActive)[Key] );
167     atomic_inc( &(p->pNoteChanged)[Key] );
168     atomic_inc( &p->notesChanged );
169     }
170    
171 schoenebeck 1663 void VirtualMidiDevice::SendNoteOffToDevice(uint8_t Key, uint8_t Velocity) {
172 schoenebeck 1659 if (Key >= MIDI_KEYS) return;
173 schoenebeck 1663 atomic_set( &(p->pNoteOffVelocity)[Key], Velocity );
174 schoenebeck 2384 if (atomic_read( &(p->pNoteIsActive)[Key] )) // only decrement if not zero
175     atomic_dec( &(p->pNoteIsActive)[Key] );
176 schoenebeck 1659 atomic_inc( &(p->pNoteChanged)[Key] );
177     atomic_inc( &p->notesChanged );
178     }
179 schoenebeck 2025
180     void VirtualMidiDevice::SendCCToDevice(uint8_t Controller, uint8_t Value) {
181     if (Controller >= MIDI_CONTROLLERS) return;
182     atomic_set( &(p->pCCValue)[Controller], Value );
183     atomic_inc( &(p->pCCChanged)[Controller] );
184     atomic_inc( &p->ccsChanged );
185     }
186 schoenebeck 1659
187     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC