/[svn]/linuxsampler/trunk/src/engines/EngineChannel.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/EngineChannel.cpp

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

revision 1761 by iliev, Fri Aug 29 15:42:06 2008 UTC revision 2330 by schoenebeck, Mon Mar 12 15:14:31 2012 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 - 2007 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2012 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 28  Line 28 
28  #include "../Sampler.h"  #include "../Sampler.h"
29  #include "../common/global_private.h"  #include "../common/global_private.h"
30  #include "../drivers/midi/MidiInstrumentMapper.h"  #include "../drivers/midi/MidiInstrumentMapper.h"
31    #include "../common/atomic.h"
32    
33  #define NO_MIDI_INSTRUMENT_MAP          -1  #define NO_MIDI_INSTRUMENT_MAP          -1
34  #define DEFAULT_MIDI_INSTRUMENT_MAP     -2  #define DEFAULT_MIDI_INSTRUMENT_MAP     -2
35    
36  namespace LinuxSampler {  namespace LinuxSampler {
37    
38      EngineChannel::EngineChannel() {      struct EngineChannel::private_data_t {
39          iMute = 0;          int     iMute;
40          bSolo = false;          bool    bSolo;
41          uiMidiBankMsb = 0;          uint8_t uiMidiProgram;
42          uiMidiBankLsb = 0;          uint8_t uiMidiBankMsb;
43          uiMidiProgram = 0;          uint8_t uiMidiBankLsb;
44          bProgramChangeReceived = bMidiBankMsbReceived = bMidiBankLsbReceived = false;          uint8_t uiMidiRpnMsb; ///< MIDI Registered Parameter Number (upper 8 bits / coarse)
45          iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;          uint8_t uiMidiRpnLsb; ///< MIDI Registered Parameter Number (lower 8 bits / fine)
46          uiVoiceCount = 0;          uint8_t uiMidiNrpnMsb; ///< MIDI Non-Registered Parameter Number (upper 8 bits / coarse)
47          uiDiskStreamCount = 0;          uint8_t uiMidiNrpnLsb; ///< MIDI Non-Registered Parameter Number (lower 8 bits / fine)
48          pSamplerChannel = NULL;          bool    bMidiBankMsbReceived;
49            bool    bMidiBankLsbReceived;
50            bool    bProgramChangeReceived;
51            bool    bMidiRpnReceived;
52            bool    bMidiNrpnReceived;
53            int     iMidiInstrumentMap;
54            atomic_t voiceCount;
55            atomic_t diskStreamCount;
56            SamplerChannel* pSamplerChannel;
57            ListenerList<FxSendCountListener*> llFxSendCountListeners;
58        };
59    
60        EngineChannel::EngineChannel() : p(new private_data_t) {
61            p->iMute = 0;
62            p->bSolo = false;
63            p->uiMidiBankMsb = 0;
64            p->uiMidiBankLsb = 0;
65            p->uiMidiProgram = 0;
66            p->bProgramChangeReceived =
67            p->bMidiBankMsbReceived =
68            p->bMidiBankLsbReceived = false;
69            p->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
70            SetVoiceCount(0);
71            SetDiskStreamCount(0);
72            p->pSamplerChannel = NULL;
73          ResetMidiRpnController();          ResetMidiRpnController();
74            ResetMidiNrpnController();
75        }
76    
77        EngineChannel::~EngineChannel() {
78            delete p;
79        }
80        
81        /**
82         * Sometimes an instrument is splitted over several files. For example
83         * the GigaStudio format may split an instrument over a certain amount
84         * of files like: "Foo.gig", "Foo.gx01", "Foo.gx02", ...
85         * This method allows to retrieve the whole list of files that is used
86         * for the currently loaded instrument on this engine channel.
87         * Calling this method with index 0 is equivalent as calling the equal
88         * named method without any argument.
89         *
90         * @param index - index of sought file name (0, 1, 2, ...)
91         * @returns file name or empty string if index out of bounds
92         */
93        String EngineChannel::InstrumentFileName(int index) {
94            return (index == 0) ? InstrumentFileName() : "";
95      }      }
96    
97      void EngineChannel::SetMute(int state) throw (Exception) {      void EngineChannel::SetMute(int state) throw (Exception) {
98          if(iMute == state) return;          if (p->iMute == state) return;
99          if(state < -1 || state > 1)          if (state < -1 || state > 1)
100              throw Exception("Invalid Mute state: " + ToString(state));              throw Exception("Invalid Mute state: " + ToString(state));
101    
102          iMute = state;          p->iMute = state;
103    
104          StatusChanged(true);          StatusChanged(true);
105      }      }
106    
107      int EngineChannel::GetMute() {      int EngineChannel::GetMute() {
108          return iMute;          return p->iMute;
109      }      }
110    
111      void EngineChannel::SetSolo(bool solo) {      void EngineChannel::SetSolo(bool solo) {
112          if(bSolo == solo) return;          if (p->bSolo == solo) return;
113          bSolo = solo;          p->bSolo = solo;
114          StatusChanged(true);          StatusChanged(true);
115      }      }
116    
117      bool EngineChannel::GetSolo() {      bool EngineChannel::GetSolo() {
118          return bSolo;          return p->bSolo;
119      }      }
120    
121      /*      /*
# Line 91  namespace LinuxSampler { Line 137  namespace LinuxSampler {
137      */      */
138    
139      uint8_t EngineChannel::GetMidiProgram() {      uint8_t EngineChannel::GetMidiProgram() {
140          return uiMidiProgram; // AFAIK atomic on all systems          return p->uiMidiProgram; // AFAIK atomic on all systems
141      }      }
142    
143      void EngineChannel::SetMidiProgram(uint8_t Program) {      void EngineChannel::SetMidiProgram(uint8_t Program) {
144          bProgramChangeReceived = true;          p->bProgramChangeReceived = true;
145          uiMidiProgram = Program; // AFAIK atomic on all systems          p->uiMidiProgram = Program; // AFAIK atomic on all systems
146      }      }
147    
148      uint8_t EngineChannel::GetMidiBankMsb() {      uint8_t EngineChannel::GetMidiBankMsb() {
149          return (bMidiBankMsbReceived && bMidiBankLsbReceived) ? uiMidiBankMsb : 0;          return (p->bMidiBankMsbReceived && p->bMidiBankLsbReceived)
150                ? p->uiMidiBankMsb : 0;
151      }      }
152    
153      void EngineChannel::SetMidiBankMsb(uint8_t BankMSB) {      void EngineChannel::SetMidiBankMsb(uint8_t BankMSB) {
154          if (bProgramChangeReceived)          if (p->bProgramChangeReceived) {
155              bProgramChangeReceived = bMidiBankLsbReceived = false;              p->bProgramChangeReceived =
156          bMidiBankMsbReceived = true;              p->bMidiBankLsbReceived = false;
157          uiMidiBankMsb = BankMSB; // AFAIK atomic on all systems          }
158            p->bMidiBankMsbReceived = true;
159            p->uiMidiBankMsb = BankMSB; // AFAIK atomic on all systems
160      }      }
161    
162      uint8_t EngineChannel::GetMidiBankLsb() {      uint8_t EngineChannel::GetMidiBankLsb() {
163          return (!bMidiBankMsbReceived && !bMidiBankLsbReceived)          return (!p->bMidiBankMsbReceived && !p->bMidiBankLsbReceived)
164                     ? 0                     ? 0
165                     : (bMidiBankMsbReceived && !bMidiBankLsbReceived)                     : (p->bMidiBankMsbReceived && !p->bMidiBankLsbReceived)
166                           ? uiMidiBankMsb                           ? p->uiMidiBankMsb
167                           : uiMidiBankLsb;                           : p->uiMidiBankLsb;
168      }      }
169    
170      void EngineChannel::SetMidiBankLsb(uint8_t BankLSB) {      void EngineChannel::SetMidiBankLsb(uint8_t BankLSB) {
171          if (bProgramChangeReceived)          if (p->bProgramChangeReceived) {
172              bProgramChangeReceived = bMidiBankMsbReceived = false;              p->bProgramChangeReceived =
173          bMidiBankLsbReceived = true;              p->bMidiBankMsbReceived = false;
174          uiMidiBankLsb = BankLSB; // AFAIK atomic on all systems          }
175            p->bMidiBankLsbReceived = true;
176            p->uiMidiBankLsb = BankLSB; // AFAIK atomic on all systems
177      }      }
178    
179      bool EngineChannel::UsesNoMidiInstrumentMap() {      bool EngineChannel::UsesNoMidiInstrumentMap() {
180          return (iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP);          return (p->iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP);
181      }      }
182    
183      bool EngineChannel::UsesDefaultMidiInstrumentMap() {      bool EngineChannel::UsesDefaultMidiInstrumentMap() {
184          return (iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP);          return (p->iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP);
185      }      }
186    
187      int EngineChannel::GetMidiInstrumentMap() throw (Exception) {      int EngineChannel::GetMidiInstrumentMap() throw (Exception) {
# Line 140  namespace LinuxSampler { Line 191  namespace LinuxSampler {
191              throw Exception("EngineChannel is using default MIDI instrument map");              throw Exception("EngineChannel is using default MIDI instrument map");
192          // check if the stored map still exists in the MIDI instrument mapper          // check if the stored map still exists in the MIDI instrument mapper
193          std::vector<int> maps = MidiInstrumentMapper::Maps();          std::vector<int> maps = MidiInstrumentMapper::Maps();
194          if (find(maps.begin(), maps.end(), iMidiInstrumentMap) == maps.end()) {          if (find(maps.begin(), maps.end(), p->iMidiInstrumentMap) == maps.end()) {
195              // it doesn't exist anymore, so fall back to NONE and throw an exception              // it doesn't exist anymore, so fall back to NONE and throw an exception
196              iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;              p->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
197              throw Exception("Assigned MIDI instrument map doesn't exist anymore, falling back to NONE");              throw Exception("Assigned MIDI instrument map doesn't exist anymore, falling back to NONE");
198          }          }
199          return iMidiInstrumentMap;          return p->iMidiInstrumentMap;
200      }      }
201    
202      void EngineChannel::SetMidiInstrumentMapToNone() {      void EngineChannel::SetMidiInstrumentMapToNone() {
203          if (iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP) return;          if (p->iMidiInstrumentMap == NO_MIDI_INSTRUMENT_MAP) return;
204          iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;          p->iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;
205          StatusChanged(true);          StatusChanged(true);
206      }      }
207    
208      void EngineChannel::SetMidiInstrumentMapToDefault() {      void EngineChannel::SetMidiInstrumentMapToDefault() {
209          if (iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP) return;          if (p->iMidiInstrumentMap == DEFAULT_MIDI_INSTRUMENT_MAP) return;
210          iMidiInstrumentMap = DEFAULT_MIDI_INSTRUMENT_MAP;          p->iMidiInstrumentMap = DEFAULT_MIDI_INSTRUMENT_MAP;
211          StatusChanged(true);          StatusChanged(true);
212      }      }
213    
214      void EngineChannel::SetMidiInstrumentMap(int MidiMap) throw (Exception) {      void EngineChannel::SetMidiInstrumentMap(int MidiMap) throw (Exception) {
215          if (iMidiInstrumentMap == MidiMap) return;          if (p->iMidiInstrumentMap == MidiMap) return;
216    
217          // check if given map actually exists in the MIDI instrument mapper          // check if given map actually exists in the MIDI instrument mapper
218          std::vector<int> maps = MidiInstrumentMapper::Maps();          std::vector<int> maps = MidiInstrumentMapper::Maps();
219          if (find(maps.begin(), maps.end(), MidiMap) == maps.end())          if (find(maps.begin(), maps.end(), MidiMap) == maps.end())
220              throw Exception("MIDI instrument map doesn't exist");              throw Exception("MIDI instrument map doesn't exist");
221          iMidiInstrumentMap = MidiMap; // assign the new map ID          p->iMidiInstrumentMap = MidiMap; // assign the new map ID
222          StatusChanged(true);          StatusChanged(true);
223      }      }
224    
225        // RPNs ...
226    
227      void EngineChannel::SetMidiRpnControllerMsb(uint8_t CtrlMSB) {      void EngineChannel::SetMidiRpnControllerMsb(uint8_t CtrlMSB) {
228          uiMidiRpnMsb = CtrlMSB;          p->uiMidiRpnMsb = CtrlMSB;
229          bMidiRpnReceived = true;          p->bMidiRpnReceived = true;
230      }      }
231    
232      void EngineChannel::SetMidiRpnControllerLsb(uint8_t CtrlLSB) {      void EngineChannel::SetMidiRpnControllerLsb(uint8_t CtrlLSB) {
233          uiMidiRpnLsb = CtrlLSB;          p->uiMidiRpnLsb = CtrlLSB;
234          bMidiRpnReceived = true;          p->bMidiRpnReceived = true;
235      }      }
236    
237      void EngineChannel::ResetMidiRpnController() {      void EngineChannel::ResetMidiRpnController() {
238          uiMidiRpnMsb = uiMidiRpnLsb = 0;          p->uiMidiRpnMsb = p->uiMidiRpnLsb = 0;
239          bMidiRpnReceived = false;          p->bMidiRpnReceived = false;
240      }      }
241    
242      int EngineChannel::GetMidiRpnController() {      int EngineChannel::GetMidiRpnController() {
243          return (bMidiRpnReceived) ? (uiMidiRpnMsb << 8) | uiMidiRpnLsb : -1;          return (p->bMidiRpnReceived) ?
244                   (p->uiMidiRpnMsb << 8) | p->uiMidiRpnLsb : -1;
245        }
246    
247        // NRPNs ...
248    
249        void EngineChannel::SetMidiNrpnControllerMsb(uint8_t CtrlMSB) {
250            p->uiMidiNrpnMsb = CtrlMSB;
251            p->bMidiNrpnReceived = true;
252        }
253    
254        void EngineChannel::SetMidiNrpnControllerLsb(uint8_t CtrlLSB) {
255            p->uiMidiNrpnLsb = CtrlLSB;
256            p->bMidiNrpnReceived = true;
257        }
258    
259        void EngineChannel::ResetMidiNrpnController() {
260            p->uiMidiNrpnMsb = p->uiMidiNrpnLsb = 0;
261            p->bMidiNrpnReceived = false;
262        }
263    
264        int EngineChannel::GetMidiNrpnController() {
265            return (p->bMidiNrpnReceived) ?
266                   (p->uiMidiNrpnMsb << 8) | p->uiMidiNrpnLsb : -1;
267      }      }
268    
269      uint EngineChannel::GetVoiceCount() {      uint EngineChannel::GetVoiceCount() {
270          return uiVoiceCount;          return atomic_read(&p->voiceCount);
271      }      }
272        
273      void EngineChannel::SetVoiceCount(uint Voices) {      void EngineChannel::SetVoiceCount(uint Voices) {
274          uiVoiceCount = Voices;          atomic_set(&p->voiceCount, Voices);
275      }      }
276    
277      uint EngineChannel::GetDiskStreamCount() {      uint EngineChannel::GetDiskStreamCount() {
278          return uiDiskStreamCount;          return atomic_read(&p->diskStreamCount);
279      }      }
280        
281      void EngineChannel::SetDiskStreamCount(uint Streams) {      void EngineChannel::SetDiskStreamCount(uint Streams) {
282          uiDiskStreamCount = Streams;          atomic_set(&p->diskStreamCount, Streams);
283      }      }
284        
285      SamplerChannel* EngineChannel::GetSamplerChannel() {      SamplerChannel* EngineChannel::GetSamplerChannel() {
286          if(pSamplerChannel == NULL) {          if (p->pSamplerChannel == NULL) {
287              std::cerr << "EngineChannel::GetSamplerChannel(): pSamplerChannel is NULL, this is a bug!\n" << std::flush;              std::cerr << "EngineChannel::GetSamplerChannel(): pSamplerChannel is NULL, this is a bug!\n" << std::flush;
288          }          }
289          return pSamplerChannel;          return p->pSamplerChannel;
290      }      }
291    
292      void EngineChannel::SetSamplerChannel(SamplerChannel* pChannel) {      void EngineChannel::SetSamplerChannel(SamplerChannel* pChannel) {
293          pSamplerChannel = pChannel;          p->pSamplerChannel = pChannel;
294      }      }
295    
296      Sampler* EngineChannel::GetSampler() {      Sampler* EngineChannel::GetSampler() {
# Line 223  namespace LinuxSampler { Line 299  namespace LinuxSampler {
299      }      }
300    
301      void EngineChannel::AddFxSendCountListener(FxSendCountListener* l) {      void EngineChannel::AddFxSendCountListener(FxSendCountListener* l) {
302          llFxSendCountListeners.AddListener(l);          p->llFxSendCountListeners.AddListener(l);
303      }      }
304    
305      void EngineChannel::RemoveFxSendCountListener(FxSendCountListener* l) {      void EngineChannel::RemoveFxSendCountListener(FxSendCountListener* l) {
306          llFxSendCountListeners.RemoveListener(l);          p->llFxSendCountListeners.RemoveListener(l);
307      }      }
308    
309      void EngineChannel::RemoveAllFxSendCountListeners() {      void EngineChannel::RemoveAllFxSendCountListeners() {
310          llFxSendCountListeners.RemoveAllListeners();          p->llFxSendCountListeners.RemoveAllListeners();
311      }      }
312    
313      void EngineChannel::fireFxSendCountChanged(int ChannelId, int NewCount) {      void EngineChannel::fireFxSendCountChanged(int ChannelId, int NewCount) {
314          for (int i = 0; i < llFxSendCountListeners.GetListenerCount(); i++) {          for (int i = 0; i < p->llFxSendCountListeners.GetListenerCount(); i++) {
315              llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);              p->llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);
316            }
317        }
318    
319        void EngineChannel::ExecuteProgramChange(uint32_t Program) {
320            uint8_t hb = (Program >> 16) & 0xff;
321            uint8_t lb = (Program >> 8) & 0xff;
322            uint8_t pc = Program & 0x7f;
323    
324            dmsg(1,("Received MIDI program change (msb=%d) (lsb=%d) (prog=%d)\n", hb ,lb, pc));
325            std::vector<int> maps = MidiInstrumentMapper::Maps();
326            if (maps.empty()) return;
327    
328            if (UsesNoMidiInstrumentMap()) return;
329            if (MidiInstrumentMapper::GetMapCount() == 0) return;
330            // retrieve the MIDI instrument map this engine channel is assigned to
331            int iMapID = (UsesDefaultMidiInstrumentMap())
332                ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : GetMidiInstrumentMap();
333            // is there an entry for this MIDI bank&prog pair in that map?
334            midi_prog_index_t midiIndex;
335            midiIndex.midi_bank_msb = hb;
336            midiIndex.midi_bank_lsb = lb;
337            midiIndex.midi_prog     = pc;
338            optional<MidiInstrumentMapper::entry_t> mapping =
339                MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
340            if (mapping) { // if mapping exists ...
341                InstrumentManager::instrument_id_t id;
342                id.FileName = mapping->InstrumentFile;
343                id.Index    = mapping->InstrumentIndex;
344                //TODO: we should switch the engine type here
345                InstrumentManager::LoadInstrumentInBackground(id, this);
346                Volume(mapping->Volume);
347          }          }
348      }      }
349    

Legend:
Removed from v.1761  
changed lines
  Added in v.2330

  ViewVC Help
Powered by ViewVC