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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1659 by schoenebeck, Sun Feb 3 00:13:27 2008 UTC revision 2521 by schoenebeck, Wed Feb 19 19:02:43 2014 UTC
# Line 1  Line 1 
1  /*  /*
2      Copyright (C) 2008 Christian Schoenebeck      Copyright (C) 2008 - 2014 Christian Schoenebeck
3   */   */
4    
5  #include "VirtualMidiDevice.h"  #include "VirtualMidiDevice.h"
# Line 8  Line 8 
8  #include "../../common/atomic.h"  #include "../../common/atomic.h"
9  #include "../../common/RingBuffer.h"  #include "../../common/RingBuffer.h"
10    
11  #define MIDI_KEYS       128  #define MIDI_KEYS               128
12    #define MIDI_CONTROLLERS        128
13    
14  // assuming VirtualMidiDevice implementation is only controlled  // assuming VirtualMidiDevice implementation is only controlled
15  // by mouse (and the user not being Billy the Kid)  // by mouse (and the user not being Billy the Kid)
# Line 16  Line 17 
17    
18  namespace LinuxSampler {  namespace LinuxSampler {
19    
20      struct _private_data_t {      struct VirtualMidiDevice::private_data_t {
21          atomic_t notesChanged; // whether some key changed at all          atomic_t notesChanged; // whether some key changed at all
22          atomic_t pNoteChanged[MIDI_KEYS]; // which key(s) changed          atomic_t pNoteChanged[MIDI_KEYS]; // which key(s) changed
23          atomic_t pNoteIsActive[MIDI_KEYS]; // status of each key (either active or inactive)          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;          RingBuffer<VirtualMidiDevice::event_t,false> events;
30    
31          _private_data_t() : events(MAX_EVENTS, 0) {}          private_data_t() : events(MAX_EVENTS, 0) {}
32      };      };
33    
34      VirtualMidiDevice::VirtualMidiDevice() {      VirtualMidiDevice::VirtualMidiDevice() : p(new private_data_t) {
         _private_data_t* p = new _private_data_t;  
         pPrivateData = p;  
35          atomic_t zero = ATOMIC_INIT(0);          atomic_t zero = ATOMIC_INIT(0);
36            atomic_t defaultVelocity = ATOMIC_INIT(127);
37            atomic_t defaultCCValue = ATOMIC_INIT(0);
38          p->notesChanged = zero;          p->notesChanged = zero;
39            p->ccsChanged   = zero;
40          for (int i = 0; i < MIDI_KEYS; i++) {          for (int i = 0; i < MIDI_KEYS; i++) {
41              p->pNoteChanged[i]  = zero;              p->pNoteChanged[i]  = zero;
42              p->pNoteIsActive[i] = zero;              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() {      VirtualMidiDevice::~VirtualMidiDevice() {
51          if (pPrivateData) delete (_private_data_t*)pPrivateData;          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) {      bool VirtualMidiDevice::SendNoteOnToSampler(uint8_t Key, uint8_t Velocity) {
59          if (Key >= MIDI_KEYS || Velocity > 127) return false;          if (Key >= MIDI_KEYS || Velocity > 127) return false;
60          _private_data_t* p = (_private_data_t*)pPrivateData;          if (Velocity == 0) {
61                return SendNoteOffToSampler(Key, Velocity);
62            }
63          event_t ev = { EVENT_TYPE_NOTEON, Key, Velocity };          event_t ev = { EVENT_TYPE_NOTEON, Key, Velocity };
64          if (p->events.write_space() <= 0) return false;          if (p->events.write_space() <= 0) return false;
65          p->events.push(&ev);          p->events.push(&ev);
# Line 51  namespace LinuxSampler { Line 68  namespace LinuxSampler {
68    
69      bool VirtualMidiDevice::SendNoteOffToSampler(uint8_t Key, uint8_t Velocity) {      bool VirtualMidiDevice::SendNoteOffToSampler(uint8_t Key, uint8_t Velocity) {
70          if (Key >= MIDI_KEYS || Velocity > 127) return false;          if (Key >= MIDI_KEYS || Velocity > 127) return false;
         _private_data_t* p = (_private_data_t*)pPrivateData;  
71          event_t ev = { EVENT_TYPE_NOTEOFF, Key, Velocity };          event_t ev = { EVENT_TYPE_NOTEOFF, Key, Velocity };
72          if (p->events.write_space() <= 0) return false;          if (p->events.write_space() <= 0) return false;
73          p->events.push(&ev);          p->events.push(&ev);
74          return true;          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 = { EVENT_TYPE_PITCHBEND, Pitch & 0x7f, (Pitch >> 7) & 0x7f };
90            if (p->events.write_space() <= 0) return false;
91            p->events.push(&ev);
92            return true;
93        }
94    
95        bool VirtualMidiDevice::SendProgramChangeToSampler(int Program) {
96            if (Program < 0 || Program > 127) return false;
97            event_t ev = { EVENT_TYPE_PROGRAM, Program, 0 };
98            if (p->events.write_space() <= 0) return false;
99            p->events.push(&ev);
100            return true;
101        }
102    
103      bool VirtualMidiDevice::GetMidiEventFromDevice(event_t& Event) {      bool VirtualMidiDevice::GetMidiEventFromDevice(event_t& Event) {
         _private_data_t* p = (_private_data_t*)pPrivateData;  
104          return (p->events.pop(&Event) > 0);          return (p->events.pop(&Event) > 0);
105      }      }
106    
107      bool VirtualMidiDevice::NotesChanged() {      bool VirtualMidiDevice::NotesChanged() {
         _private_data_t* p = (_private_data_t*)pPrivateData;  
108          int c = atomic_read( &p->notesChanged );          int c = atomic_read( &p->notesChanged );
109          atomic_sub(c, &p->notesChanged );          atomic_sub(c, &p->notesChanged );
110          return c;          return c;
111      }      }
112        
113        bool VirtualMidiDevice::ControllersChanged() {
114            int c = atomic_read( &p->ccsChanged );
115            atomic_sub(c, &p->ccsChanged );
116            return c;
117        }
118    
119      bool VirtualMidiDevice::NoteChanged(uint8_t Key) {      bool VirtualMidiDevice::NoteChanged(uint8_t Key) {
         _private_data_t* p = (_private_data_t*)pPrivateData;  
120          int c = atomic_read( &(p->pNoteChanged)[Key] );          int c = atomic_read( &(p->pNoteChanged)[Key] );
121          atomic_sub(c, &(p->pNoteChanged)[Key] );          atomic_sub(c, &(p->pNoteChanged)[Key] );
122          return c;          return c;
123      }      }
124        
125        bool VirtualMidiDevice::ControllerChanged(uint8_t Controller) {
126            int c = atomic_read( &(p->pCCChanged)[Controller] );
127            atomic_sub(c, &(p->pCCChanged)[Controller] );
128            return c;
129        }
130    
131      bool VirtualMidiDevice::NoteIsActive(uint8_t Key) {      bool VirtualMidiDevice::NoteIsActive(uint8_t Key) {
         _private_data_t* p = (_private_data_t*)pPrivateData;  
132          return atomic_read( &(p->pNoteIsActive)[Key] );          return atomic_read( &(p->pNoteIsActive)[Key] );
133      }      }
134    
135      void VirtualMidiDevice::SendNoteOnToDevice(uint8_t Key, uint8_t /*Velocity*/) {      uint8_t VirtualMidiDevice::NoteOnVelocity(uint8_t Key) {
136            return atomic_read( &(p->pNoteOnVelocity)[Key] );
137        }
138    
139        uint8_t VirtualMidiDevice::NoteOffVelocity(uint8_t Key) {
140            return atomic_read( &(p->pNoteOffVelocity)[Key] );
141        }
142        
143        uint8_t VirtualMidiDevice::ControllerValue(uint8_t Controller) {
144            return atomic_read( &(p->pCCValue)[Controller] );
145        }
146    
147        void VirtualMidiDevice::SendNoteOnToDevice(uint8_t Key, uint8_t Velocity) {
148          if (Key >= MIDI_KEYS) return;          if (Key >= MIDI_KEYS) return;
149          _private_data_t* p = (_private_data_t*)pPrivateData;          if (Velocity == 0) {
150                SendNoteOffToDevice(Key, Velocity);
151                return;
152            }
153            atomic_set( &(p->pNoteOnVelocity)[Key], Velocity );
154          atomic_inc( &(p->pNoteIsActive)[Key] );          atomic_inc( &(p->pNoteIsActive)[Key] );
155          atomic_inc( &(p->pNoteChanged)[Key] );          atomic_inc( &(p->pNoteChanged)[Key] );
156          atomic_inc( &p->notesChanged );          atomic_inc( &p->notesChanged );
157      }      }
158    
159      void VirtualMidiDevice::SendNoteOffToDevice(uint8_t Key, uint8_t /*Velocity*/) {      void VirtualMidiDevice::SendNoteOffToDevice(uint8_t Key, uint8_t Velocity) {
160          if (Key >= MIDI_KEYS) return;          if (Key >= MIDI_KEYS) return;
161          _private_data_t* p = (_private_data_t*)pPrivateData;          atomic_set( &(p->pNoteOffVelocity)[Key], Velocity );
162          atomic_dec( &(p->pNoteIsActive)[Key] );          if (atomic_read( &(p->pNoteIsActive)[Key] )) // only decrement if not zero
163                atomic_dec( &(p->pNoteIsActive)[Key] );
164          atomic_inc( &(p->pNoteChanged)[Key] );          atomic_inc( &(p->pNoteChanged)[Key] );
165          atomic_inc( &p->notesChanged );          atomic_inc( &p->notesChanged );
166      }      }
167        
168        void VirtualMidiDevice::SendCCToDevice(uint8_t Controller, uint8_t Value) {
169            if (Controller >= MIDI_CONTROLLERS) return;
170            atomic_set( &(p->pCCValue)[Controller], Value );
171            atomic_inc( &(p->pCCChanged)[Controller] );
172            atomic_inc( &p->ccsChanged );
173        }
174    
175  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.1659  
changed lines
  Added in v.2521

  ViewVC Help
Powered by ViewVC