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

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

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

revision 1653 by schoenebeck, Wed Jan 30 01:51:46 2008 UTC revision 1835 by iliev, Mon Feb 16 17:56:50 2009 UTC
# Line 24  Line 24 
24  #include "EngineChannel.h"  #include "EngineChannel.h"
25    
26  #include "../../common/global_private.h"  #include "../../common/global_private.h"
27    #include "../../Sampler.h"
28    
29  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
30    
31      EngineChannel::EngineChannel() :      EngineChannel::EngineChannel() :
32          InstrumentChangeCommandReader(InstrumentChangeCommand) {          InstrumentChangeCommandReader(InstrumentChangeCommand),
33            virtualMidiDevicesReader_AudioThread(virtualMidiDevices),
34            virtualMidiDevicesReader_MidiThread(virtualMidiDevices)
35        {
36          pMIDIKeyInfo = new midi_key_info_t[128];          pMIDIKeyInfo = new midi_key_info_t[128];
37          pEngine      = NULL;          pEngine      = NULL;
38          pInstrument  = NULL;          pInstrument  = NULL;
# Line 56  namespace LinuxSampler { namespace gig { Line 60  namespace LinuxSampler { namespace gig {
60          SoloMode       = false;          SoloMode       = false;
61          PortamentoMode = false;          PortamentoMode = false;
62          PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT;          PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT;
63    
64            // reset the instrument change command struct (need to be done
65            // twice, as it is double buffered)
66            {
67                instrument_change_command_t& cmd = InstrumentChangeCommand.GetConfigForUpdate();
68                cmd.pDimRegionsInUse = NULL;
69                cmd.pInstrument = NULL;
70                cmd.bChangeInstrument = false;
71            }
72            {
73                instrument_change_command_t& cmd = InstrumentChangeCommand.SwitchConfig();
74                cmd.pDimRegionsInUse = NULL;
75                cmd.pInstrument = NULL;
76                cmd.bChangeInstrument = false;
77            }
78      }      }
79    
80      EngineChannel::~EngineChannel() {      EngineChannel::~EngineChannel() {
81          DisconnectAudioOutputDevice();          DisconnectAudioOutputDevice();
82    
83            // In case the channel was removed before the instrument was
84            // fully loaded, try to give back instrument again (see bug #113)
85            instrument_change_command_t& cmd = ChangeInstrument(NULL);
86            if (cmd.pInstrument) {
87                    Engine::instruments.HandBack(cmd.pInstrument, this);
88            }
89            ///////
90    
91          if (pEventQueue) delete pEventQueue;          if (pEventQueue) delete pEventQueue;
92          if (pActiveKeys) delete pActiveKeys;          if (pActiveKeys) delete pActiveKeys;
93          if (pMIDIKeyInfo) delete[] pMIDIKeyInfo;          if (pMIDIKeyInfo) delete[] pMIDIKeyInfo;
# Line 326  namespace LinuxSampler { namespace gig { Line 354  namespace LinuxSampler { namespace gig {
354                  // release the currently loaded instrument                  // release the currently loaded instrument
355                  Engine::instruments.HandBackInstrument(cmd.pInstrument, this, d);                  Engine::instruments.HandBackInstrument(cmd.pInstrument, this, d);
356              }              }
357    
358              if (d) delete d;              if (d) delete d;
359    
360              // release all active dimension regions to resource              // release all active dimension regions to resource
# Line 448  namespace LinuxSampler { namespace gig { Line 477  namespace LinuxSampler { namespace gig {
477          }          }
478          fxSends.push_back(pFxSend);          fxSends.push_back(pFxSend);
479          if (pEngine) pEngine->Enable();          if (pEngine) pEngine->Enable();
480          fireFxSendCountChanged(iSamplerChannelIndex, GetFxSendCount());          fireFxSendCountChanged(GetSamplerChannel()->Index(), GetFxSendCount());
481    
482          return pFxSend;          return pFxSend;
483      }      }
# Line 487  namespace LinuxSampler { namespace gig { Line 516  namespace LinuxSampler { namespace gig {
516              }              }
517          }          }
518          if (pEngine) pEngine->Enable();          if (pEngine) pEngine->Enable();
519          fireFxSendCountChanged(iSamplerChannelIndex, GetFxSendCount());          fireFxSendCountChanged(GetSamplerChannel()->Index(), GetFxSendCount());
520      }      }
521    
522      /**      /**
# Line 508  namespace LinuxSampler { namespace gig { Line 537  namespace LinuxSampler { namespace gig {
537              event.pEngineChannel      = this;              event.pEngineChannel      = this;
538              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
539              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
540              // inform instrument editor(s), if any ...              // inform connected virtual MIDI devices if any ...
541              pEngine->instruments.TrySendNoteOnToEditors(Key, Velocity, pInstrument);              // (e.g. virtual MIDI keyboard in instrument editor(s))
542                ArrayList<VirtualMidiDevice*>& devices =
543                    const_cast<ArrayList<VirtualMidiDevice*>&>(
544                        virtualMidiDevicesReader_MidiThread.Lock()
545                    );
546                for (int i = 0; i < devices.size(); i++) {
547                    devices[i]->SendNoteOnToDevice(Key, Velocity);
548                }
549                virtualMidiDevicesReader_MidiThread.Unlock();
550          }          }
551      }      }
552    
# Line 536  namespace LinuxSampler { namespace gig { Line 573  namespace LinuxSampler { namespace gig {
573              event.pEngineChannel      = this;              event.pEngineChannel      = this;
574              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
575              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
576              // inform instrument editor(s), if any ...              // inform connected virtual MIDI devices if any ...
577              pEngine->instruments.TrySendNoteOnToEditors(Key, Velocity, pInstrument);              // (e.g. virtual MIDI keyboard in instrument editor(s))
578                ArrayList<VirtualMidiDevice*>& devices =
579                    const_cast<ArrayList<VirtualMidiDevice*>&>(
580                        virtualMidiDevicesReader_MidiThread.Lock()
581                    );
582                for (int i = 0; i < devices.size(); i++) {
583                    devices[i]->SendNoteOnToDevice(Key, Velocity);
584                }
585                virtualMidiDevicesReader_MidiThread.Unlock();
586          }          }
587      }      }
588    
# Line 559  namespace LinuxSampler { namespace gig { Line 604  namespace LinuxSampler { namespace gig {
604              event.pEngineChannel      = this;              event.pEngineChannel      = this;
605              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
606              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
607              // inform instrument editor(s), if any ...              // inform connected virtual MIDI devices if any ...
608              pEngine->instruments.TrySendNoteOffToEditors(Key, Velocity, pInstrument);              // (e.g. virtual MIDI keyboard in instrument editor(s))
609                ArrayList<VirtualMidiDevice*>& devices =
610                    const_cast<ArrayList<VirtualMidiDevice*>&>(
611                        virtualMidiDevicesReader_MidiThread.Lock()
612                    );
613                for (int i = 0; i < devices.size(); i++) {
614                    devices[i]->SendNoteOffToDevice(Key, Velocity);
615                }
616                virtualMidiDevicesReader_MidiThread.Unlock();
617          }          }
618      }      }
619    
# Line 587  namespace LinuxSampler { namespace gig { Line 640  namespace LinuxSampler { namespace gig {
640              event.pEngineChannel      = this;              event.pEngineChannel      = this;
641              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
642              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
643              // inform instrument editor(s), if any ...              // inform connected virtual MIDI devices if any ...
644              pEngine->instruments.TrySendNoteOffToEditors(Key, Velocity, pInstrument);              // (e.g. virtual MIDI keyboard in instrument editor(s))
645                ArrayList<VirtualMidiDevice*>& devices =
646                    const_cast<ArrayList<VirtualMidiDevice*>&>(
647                        virtualMidiDevicesReader_MidiThread.Lock()
648                    );
649                for (int i = 0; i < devices.size(); i++) {
650                    devices[i]->SendNoteOffToDevice(Key, Velocity);
651                }
652                virtualMidiDevicesReader_MidiThread.Unlock();
653          }          }
654      }      }
655    
# Line 702  namespace LinuxSampler { namespace gig { Line 763  namespace LinuxSampler { namespace gig {
763          MidiVolume     = 1.0;          MidiVolume     = 1.0;
764          GlobalPanLeft  = 1.0f;          GlobalPanLeft  = 1.0f;
765          GlobalPanRight = 1.0f;          GlobalPanRight = 1.0f;
766            iLastPanRequest = 64;
767          GlobalTranspose = 0;          GlobalTranspose = 0;
768          // set all MIDI controller values to zero          // set all MIDI controller values to zero
769          memset(ControllerTable, 0x00, 129);          memset(ControllerTable, 0x00, 129);
# Line 728  namespace LinuxSampler { namespace gig { Line 790  namespace LinuxSampler { namespace gig {
790       *                  current audio cycle       *                  current audio cycle
791       */       */
792      void EngineChannel::ImportEvents(uint Samples) {      void EngineChannel::ImportEvents(uint Samples) {
793            // import events from pure software MIDI "devices"
794            // (e.g. virtual keyboard in instrument editor)
795            {
796                const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices
797                Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);
798                VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device
799                // as we're going to (carefully) write some status to the
800                // synchronized struct, we cast away the const
801                ArrayList<VirtualMidiDevice*>& devices =
802                    const_cast<ArrayList<VirtualMidiDevice*>&>(virtualMidiDevicesReader_AudioThread.Lock());
803                // iterate through all virtual MIDI devices
804                for (int i = 0; i < devices.size(); i++) {
805                    VirtualMidiDevice* pDev = devices[i];
806                    // I think we can simply flush the whole FIFO(s), the user shouldn't be so fast ;-)
807                    while (pDev->GetMidiEventFromDevice(devEvent)) {
808                        event.Type =
809                            (devEvent.Type == VirtualMidiDevice::EVENT_TYPE_NOTEON) ?
810                                Event::type_note_on : Event::type_note_off;
811                        event.Param.Note.Key      = devEvent.Key;
812                        event.Param.Note.Velocity = devEvent.Velocity;
813                        event.pEngineChannel      = this;
814                        // copy event to internal event list
815                        if (pEvents->poolIsEmpty()) {
816                            dmsg(1,("Event pool emtpy!\n"));
817                            goto exitVirtualDevicesLoop;
818                        }
819                        *pEvents->allocAppend() = event;
820                    }
821                }
822            }
823            exitVirtualDevicesLoop:
824            virtualMidiDevicesReader_AudioThread.Unlock();
825    
826            // import events from the regular MIDI devices
827          RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();          RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader();
828          Event* pEvent;          Event* pEvent;
829          while (true) {          while (true) {
# Line 773  namespace LinuxSampler { namespace gig { Line 869  namespace LinuxSampler { namespace gig {
869          if (pEngine) pEngine->Enable();          if (pEngine) pEngine->Enable();
870      }      }
871    
872        void EngineChannel::Connect(VirtualMidiDevice* pDevice) {
873            // double buffer ... double work ...
874            {
875                ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.GetConfigForUpdate();
876                devices.add(pDevice);
877            }
878            {
879                ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.SwitchConfig();
880                devices.add(pDevice);
881            }
882        }
883    
884        void EngineChannel::Disconnect(VirtualMidiDevice* pDevice) {
885            // double buffer ... double work ...
886            {
887                ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.GetConfigForUpdate();
888                devices.remove(pDevice);
889            }
890            {
891                ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.SwitchConfig();
892                devices.remove(pDevice);
893            }
894        }
895    
896      float EngineChannel::Volume() {      float EngineChannel::Volume() {
897          return GlobalVolume;          return GlobalVolume;
898      }      }
# Line 782  namespace LinuxSampler { namespace gig { Line 902  namespace LinuxSampler { namespace gig {
902          bStatusChanged = true; // status of engine channel has changed, so set notify flag          bStatusChanged = true; // status of engine channel has changed, so set notify flag
903      }      }
904    
905        float EngineChannel::Pan() {
906            return float(iLastPanRequest - 64) / 64.0f;
907        }
908    
909        void EngineChannel::Pan(float f) {
910            int iMidiPan = int(f * 64.0f) + 64;
911            if (iMidiPan > 127) iMidiPan = 127;
912            else if (iMidiPan < 0) iMidiPan = 0;
913            GlobalPanLeft  = Engine::PanCurve[128 - iMidiPan];
914            GlobalPanRight = Engine::PanCurve[iMidiPan];
915            iLastPanRequest = iMidiPan;
916        }
917    
918      uint EngineChannel::Channels() {      uint EngineChannel::Channels() {
919          return 2;          return 2;
920      }      }

Legend:
Removed from v.1653  
changed lines
  Added in v.1835

  ViewVC Help
Powered by ViewVC