/[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 1254 by iliev, Sun Jun 24 20:02:56 2007 UTC revision 3687 by schoenebeck, Thu Jan 2 22:37:07 2020 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 - 2020 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 25  Line 25 
25    
26  #include <algorithm>  #include <algorithm>
27    
28    #include "../Sampler.h"
29    #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 7 bits / coarse)
45          iMidiInstrumentMap = NO_MIDI_INSTRUMENT_MAP;          uint8_t uiMidiRpnLsb; ///< MIDI Registered Parameter Number (lower 7 bits / fine)
46          ResetMidiRpnController();          uint8_t uiMidiNrpnMsb; ///< MIDI Non-Registered Parameter Number (upper 7 bits / coarse)
47            uint8_t uiMidiNrpnLsb; ///< MIDI Non-Registered Parameter Number (lower 7 bits / fine)
48            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            ResetMidiRpnParameter();
74            ResetMidiNrpnParameter();
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 86  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 135  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      void EngineChannel::SetMidiRpnControllerMsb(uint8_t CtrlMSB) {      // RPNs ...
226          uiMidiRpnMsb = CtrlMSB;  
227          bMidiRpnReceived = true;      void EngineChannel::SetMidiRpnParameterMsb(uint8_t ParamMSB) {
228            p->uiMidiRpnMsb = ParamMSB & 127;
229            p->bMidiRpnReceived = true;
230        }
231    
232        void EngineChannel::SetMidiRpnControllerMsb(uint8_t CtrlMSB) { // deprecated API
233            SetMidiRpnParameterMsb(CtrlMSB);
234        }
235    
236        void EngineChannel::SetMidiRpnParameterLsb(uint8_t ParamLSB) {
237            p->uiMidiRpnLsb = ParamLSB & 127;
238            p->bMidiRpnReceived = true;
239      }      }
240    
241      void EngineChannel::SetMidiRpnControllerLsb(uint8_t CtrlLSB) {      void EngineChannel::SetMidiRpnControllerLsb(uint8_t CtrlLSB) { // deprecated API
242          uiMidiRpnLsb = CtrlLSB;          SetMidiRpnParameterLsb(CtrlLSB);
         bMidiRpnReceived = true;  
243      }      }
244    
245      void EngineChannel::ResetMidiRpnController() {      void EngineChannel::ResetMidiRpnParameter() {
246          uiMidiRpnMsb = uiMidiRpnLsb = 0;          p->uiMidiRpnMsb = p->uiMidiRpnLsb = 0;
247          bMidiRpnReceived = false;          p->bMidiRpnReceived = false;
248      }      }
249    
250      int EngineChannel::GetMidiRpnController() {      void EngineChannel::ResetMidiRpnController() { // deprecated API
251          return (bMidiRpnReceived) ? (uiMidiRpnMsb << 8) | uiMidiRpnLsb : -1;          ResetMidiRpnParameter();
252        }
253    
254        int EngineChannel::GetMidiRpnParameter() {
255            return (p->bMidiRpnReceived) ?
256                   (p->uiMidiRpnMsb << 7) | p->uiMidiRpnLsb : -1;
257        }
258    
259        int EngineChannel::GetMidiRpnController() { // deprecated API
260            return (p->bMidiRpnReceived) ?
261                   (p->uiMidiRpnMsb << 8) | p->uiMidiRpnLsb : -1;
262        }
263    
264        // NRPNs ...
265    
266        void EngineChannel::SetMidiNrpnParameterMsb(uint8_t ParamMSB) {
267            p->uiMidiNrpnMsb = ParamMSB & 127;
268            p->bMidiNrpnReceived = true;
269        }
270    
271        void EngineChannel::SetMidiNrpnControllerMsb(uint8_t CtrlMSB) { // deprecated API
272            SetMidiNrpnParameterMsb(CtrlMSB);
273        }
274    
275        void EngineChannel::SetMidiNrpnParameterLsb(uint8_t ParamLSB) {
276            p->uiMidiNrpnLsb = ParamLSB & 127;
277            p->bMidiNrpnReceived = true;
278        }
279    
280        void EngineChannel::SetMidiNrpnControllerLsb(uint8_t CtrlLSB) { // deprecated API
281            SetMidiNrpnParameterLsb(CtrlLSB);
282        }
283    
284        void EngineChannel::ResetMidiNrpnParameter() {
285            p->uiMidiNrpnMsb = p->uiMidiNrpnLsb = 0;
286            p->bMidiNrpnReceived = false;
287        }
288    
289        void EngineChannel::ResetMidiNrpnController() { // deprecated API
290            ResetMidiNrpnParameter();
291        }
292    
293        int EngineChannel::GetMidiNrpnParameter() {
294            return (p->bMidiNrpnReceived) ?
295                   (p->uiMidiNrpnMsb << 7)  | p->uiMidiNrpnLsb : -1;
296        }
297    
298        int EngineChannel::GetMidiNrpnController() { // deprecated API
299            return (p->bMidiNrpnReceived) ?
300                   (p->uiMidiNrpnMsb << 8) | p->uiMidiNrpnLsb : -1;
301        }
302    
303        uint EngineChannel::GetVoiceCount() {
304            return atomic_read(&p->voiceCount);
305        }
306    
307        void EngineChannel::SetVoiceCount(uint Voices) {
308            atomic_set(&p->voiceCount, Voices);
309        }
310    
311        uint EngineChannel::GetDiskStreamCount() {
312            return atomic_read(&p->diskStreamCount);
313        }
314    
315        void EngineChannel::SetDiskStreamCount(uint Streams) {
316            atomic_set(&p->diskStreamCount, Streams);
317        }
318    
319        SamplerChannel* EngineChannel::GetSamplerChannel() {
320            if (p->pSamplerChannel == NULL) {
321                std::cerr << "EngineChannel::GetSamplerChannel(): pSamplerChannel is NULL, this is a bug!\n" << std::flush;
322            }
323            return p->pSamplerChannel;
324        }
325    
326        void EngineChannel::SetSamplerChannel(SamplerChannel* pChannel) {
327            p->pSamplerChannel = pChannel;
328        }
329    
330        Sampler* EngineChannel::GetSampler() {
331            if (GetSamplerChannel() == NULL) return NULL;
332            return GetSamplerChannel()->GetSampler();
333      }      }
334    
335      void EngineChannel::AddFxSendCountListener(FxSendCountListener* l) {      void EngineChannel::AddFxSendCountListener(FxSendCountListener* l) {
336          llFxSendCountListeners.AddListener(l);          p->llFxSendCountListeners.AddListener(l);
337      }      }
338    
339      void EngineChannel::RemoveFxSendCountListener(FxSendCountListener* l) {      void EngineChannel::RemoveFxSendCountListener(FxSendCountListener* l) {
340          llFxSendCountListeners.RemoveListener(l);          p->llFxSendCountListeners.RemoveListener(l);
341      }      }
342    
343      void EngineChannel::RemoveAllFxSendCountListeners() {      void EngineChannel::RemoveAllFxSendCountListeners() {
344          llFxSendCountListeners.RemoveAllListeners();          p->llFxSendCountListeners.RemoveAllListeners();
345      }      }
346    
347      void EngineChannel::fireFxSendCountChanged(int ChannelId, int NewCount) {      void EngineChannel::fireFxSendCountChanged(int ChannelId, int NewCount) {
348          for (int i = 0; i < llFxSendCountListeners.GetListenerCount(); i++) {          for (int i = 0; i < p->llFxSendCountListeners.GetListenerCount(); i++) {
349              llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);              p->llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);
350            }
351        }
352    
353        void EngineChannel::ExecuteProgramChange(uint32_t Program) {
354            uint8_t hb = (Program >> 16) & 0xff;
355            uint8_t lb = (Program >> 8) & 0xff;
356            uint8_t pc = Program & 0x7f;
357    
358            dmsg(1,("Received MIDI program change (msb=%d) (lsb=%d) (prog=%d)\n", hb ,lb, pc));
359            std::vector<int> maps = MidiInstrumentMapper::Maps();
360            if (maps.empty()) return;
361    
362            if (UsesNoMidiInstrumentMap()) return;
363            if (MidiInstrumentMapper::GetMapCount() == 0) return;
364            // retrieve the MIDI instrument map this engine channel is assigned to
365            int iMapID = (UsesDefaultMidiInstrumentMap())
366                ? MidiInstrumentMapper::GetDefaultMap() /*default*/ : GetMidiInstrumentMap();
367            // is there an entry for this MIDI bank&prog pair in that map?
368            midi_prog_index_t midiIndex;
369            midiIndex.midi_bank_msb = hb;
370            midiIndex.midi_bank_lsb = lb;
371            midiIndex.midi_prog     = pc;
372            optional<MidiInstrumentMapper::entry_t> mapping =
373                MidiInstrumentMapper::GetEntry(iMapID, midiIndex);
374            if (mapping) { // if mapping exists ...
375                InstrumentManager::instrument_id_t id;
376                id.FileName = mapping->InstrumentFile;
377                id.Index    = mapping->InstrumentIndex;
378                //TODO: we should switch the engine type here
379                InstrumentManager::LoadInstrumentInBackground(id, this);
380                Volume(mapping->Volume);
381          }          }
382      }      }
383    

Legend:
Removed from v.1254  
changed lines
  Added in v.3687

  ViewVC Help
Powered by ViewVC