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

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

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

revision 2871 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC revision 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 UTC
# Line 383  namespace LinuxSampler { Line 383  namespace LinuxSampler {
383              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
384              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
385              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
386              event.pEngineChannel      = this;              event.pEngineChannel      = this;
387              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
388              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 425  namespace LinuxSampler { Line 424  namespace LinuxSampler {
424              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
425              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
426              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
427              event.pEngineChannel      = this;              event.pEngineChannel      = this;
428              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
429              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 462  namespace LinuxSampler { Line 460  namespace LinuxSampler {
460              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
461              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
462              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
463              event.pEngineChannel      = this;              event.pEngineChannel      = this;
464              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
465              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 504  namespace LinuxSampler { Line 501  namespace LinuxSampler {
501              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
502              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
503              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
504              event.pEngineChannel      = this;              event.pEngineChannel      = this;
505              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
506              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 539  namespace LinuxSampler { Line 535  namespace LinuxSampler {
535              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
536              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
537              event.Param.Pitch.Channel = MidiChannel;              event.Param.Pitch.Channel = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
538              event.pEngineChannel    = this;              event.pEngineChannel    = this;
539              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
540              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 569  namespace LinuxSampler { Line 564  namespace LinuxSampler {
564              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
565              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
566              event.Param.Pitch.Channel = MidiChannel;              event.Param.Pitch.Channel = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
567              event.pEngineChannel    = this;              event.pEngineChannel    = this;
568              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
569              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 596  namespace LinuxSampler { Line 590  namespace LinuxSampler {
590              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
591              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
592              event.Param.CC.Channel    = MidiChannel;              event.Param.CC.Channel    = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
593              event.pEngineChannel      = this;              event.pEngineChannel      = this;
594              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
595              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 628  namespace LinuxSampler { Line 621  namespace LinuxSampler {
621              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
622              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
623              event.Param.CC.Channel    = MidiChannel;              event.Param.CC.Channel    = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
624              event.pEngineChannel      = this;              event.pEngineChannel      = this;
625              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
626              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 646  namespace LinuxSampler { Line 638  namespace LinuxSampler {
638              event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts              event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts
639              event.Param.ChannelPressure.Value   = Value;              event.Param.ChannelPressure.Value   = Value;
640              event.Param.ChannelPressure.Channel = MidiChannel;              event.Param.ChannelPressure.Channel = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
641              event.pEngineChannel                = this;              event.pEngineChannel                = this;
642              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
643              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 664  namespace LinuxSampler { Line 655  namespace LinuxSampler {
655              event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts              event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts
656              event.Param.ChannelPressure.Value   = Value;              event.Param.ChannelPressure.Value   = Value;
657              event.Param.ChannelPressure.Channel = MidiChannel;              event.Param.ChannelPressure.Channel = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
658              event.pEngineChannel                = this;              event.pEngineChannel                = this;
659              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
660              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 682  namespace LinuxSampler { Line 672  namespace LinuxSampler {
672              event.Param.NotePressure.Key     = Key;              event.Param.NotePressure.Key     = Key;
673              event.Param.NotePressure.Value   = Value;              event.Param.NotePressure.Value   = Value;
674              event.Param.NotePressure.Channel = MidiChannel;              event.Param.NotePressure.Channel = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
675              event.pEngineChannel             = this;              event.pEngineChannel             = this;
676              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
677              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 700  namespace LinuxSampler { Line 689  namespace LinuxSampler {
689              event.Param.NotePressure.Key     = Key;              event.Param.NotePressure.Key     = Key;
690              event.Param.NotePressure.Value   = Value;              event.Param.NotePressure.Value   = Value;
691              event.Param.NotePressure.Channel = MidiChannel;              event.Param.NotePressure.Channel = MidiChannel;
             memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes  
692              event.pEngineChannel             = this;              event.pEngineChannel             = this;
693              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
694              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
695          }          }
696      }      }
697    
698        bool AbstractEngineChannel::applyTranspose(Event* event) {
699            if (event->Type != Event::type_note_on && event->Type != Event::type_note_off)
700                return true; // event OK (not a note event, nothing to do with it here)
701    
702            //HACK: we should better add the transpose value only to the most mandatory places (like for retrieving the region and calculating the tuning), because otherwise voices will unintendedly survive when changing transpose while playing
703            const int k = event->Param.Note.Key + GlobalTranspose;
704            if (k < 0 || k > 127)
705                return false; // bad event, drop it
706    
707            event->Param.Note.Key = k;
708    
709            return true; // event OK
710        }
711    
712      /**      /**
713       * Copy all events from the engine channel's input event queue buffer to       * Copy all events from the engine channel's input event queue buffer to
714       * the internal event list. This will be done at the beginning of each       * the internal event list. This will be done at the beginning of each
# Line 743  namespace LinuxSampler { Line 745  namespace LinuxSampler {
745                              event.Param.Note.Key      = devEvent.Arg1;                              event.Param.Note.Key      = devEvent.Arg1;
746                              event.Param.Note.Velocity = devEvent.Arg2;                              event.Param.Note.Velocity = devEvent.Arg2;
747                              event.Param.Note.Channel  = channel;                              event.Param.Note.Channel  = channel;
748                                // apply transpose setting to (note on/off) event
749                                if (!applyTranspose(&event))
750                                    continue; // note value is out of range, so drop this event
751                                // assign a new note to this note-on event
752                                if (!pEngine->LaunchNewNote(this, &event))
753                                    continue; // failed launching new note, so drop this event
754                              break;                              break;
755                          case VirtualMidiDevice::EVENT_TYPE_NOTEOFF:                          case VirtualMidiDevice::EVENT_TYPE_NOTEOFF:
756                              event.Type = Event::type_note_off;                              event.Type = Event::type_note_off;
757                              event.Param.Note.Key      = devEvent.Arg1;                              event.Param.Note.Key      = devEvent.Arg1;
758                              event.Param.Note.Velocity = devEvent.Arg2;                              event.Param.Note.Velocity = devEvent.Arg2;
759                              event.Param.Note.Channel  = channel;                              event.Param.Note.Channel  = channel;
760                                if (!applyTranspose(&event))
761                                    continue; // note value is out of range, so drop this event
762                              break;                              break;
763                          case VirtualMidiDevice::EVENT_TYPE_CC:                          case VirtualMidiDevice::EVENT_TYPE_CC:
764                              switch (devEvent.Arg1) {                              switch (devEvent.Arg1) {
# Line 778  namespace LinuxSampler { Line 788  namespace LinuxSampler {
788                                        << devEvent.Type << "). This is a bug!";                                        << devEvent.Type << "). This is a bug!";
789                              continue;                              continue;
790                      }                      }
                     memset(&event.Format, 0, sizeof(event.Format)); // init format specific stuff with zeroes  
791                      event.pEngineChannel = this;                      event.pEngineChannel = this;
792                      // copy event to internal event list                      // copy event to internal event list
793                      if (pEvents->poolIsEmpty()) {                      if (pEvents->poolIsEmpty()) {
# Line 805  namespace LinuxSampler { Line 814  namespace LinuxSampler {
814                  pEvent->ResetFragmentPos();                  pEvent->ResetFragmentPos();
815                  break;                  break;
816              }              }
             // copy event to internal event list  
817              if (pEvents->poolIsEmpty()) {              if (pEvents->poolIsEmpty()) {
818                  dmsg(1,("Event pool emtpy!\n"));                  dmsg(1,("Event pool emtpy!\n"));
819                  break;                  break;
820              }              }
821                // apply transpose setting to (note on/off) event
822                if (!applyTranspose(pEvent))
823                    continue; // it's a note event which has a note value out of range, so drop this event
824                // assign a new note to this event (if its a note-on event)
825                if (pEvent->Type == Event::type_note_on)
826                    if (!pEngine->LaunchNewNote(this, pEvent))
827                        continue; // failed launching new note, so drop this event
828                // copy event to internal event list
829              *pEvents->allocAppend() = *pEvent;              *pEvents->allocAppend() = *pEvent;
830          }          }
831          eventQueueReader.free(); // free all copied events from input queue          eventQueueReader.free(); // free all copied events from input queue
# Line 830  namespace LinuxSampler { Line 846  namespace LinuxSampler {
846       *       *
847       * @param pEvent - event to be scheduled in future (event data will be copied)       * @param pEvent - event to be scheduled in future (event data will be copied)
848       * @param delay - amount of microseconds in future (from now) when event shall be processed       * @param delay - amount of microseconds in future (from now) when event shall be processed
849       * @returns unique event ID of scheduled new event, or a negative number on error       * @returns unique event ID of scheduled new event, or NULL on error
850       */       */
851      int AbstractEngineChannel::ScheduleEventMicroSec(const Event* pEvent, int delay) {      event_id_t AbstractEngineChannel::ScheduleEventMicroSec(const Event* pEvent, int delay) {
852          dmsg(3,("AbstractEngineChannel::ScheduleEventMicroSec(Event.Type=%d,delay=%d)\n", pEvent->Type, delay));          dmsg(3,("AbstractEngineChannel::ScheduleEventMicroSec(Event.Type=%d,delay=%d)\n", pEvent->Type, delay));
853          RTList<Event>::Iterator itEvent = pEvents->allocAppend();          RTList<Event>::Iterator itEvent = pEvents->allocAppend();
854          if (!itEvent) {          if (!itEvent) {
855              dmsg(1,("AbstractEngineChannel::ScheduleEventMicroSec(): Event pool emtpy!\n"));              dmsg(1,("AbstractEngineChannel::ScheduleEventMicroSec(): Event pool emtpy!\n"));
856              return -1;              return 0;
857          }          }
858          RTList<ScheduledEvent>::Iterator itNode = delayedEvents.schedulerNodes.allocAppend();          RTList<ScheduledEvent>::Iterator itNode = delayedEvents.schedulerNodes.allocAppend();
859          if (!itNode) { // scheduler node pool empty ...          if (!itNode) { // scheduler node pool empty ...
860              dmsg(1,("AbstractEngineChannel::ScheduleEventMicroSec(): ScheduledEvent pool empty!\n"));              dmsg(1,("AbstractEngineChannel::ScheduleEventMicroSec(): ScheduledEvent pool empty!\n"));
861              pEvents->free(itEvent);              pEvents->free(itEvent);
862              return -1;              return 0;
863          }          }
864          // copy passed event          // copy passed event
865          *itEvent = *pEvent;          *itEvent = *pEvent;
# Line 864  namespace LinuxSampler { Line 880  namespace LinuxSampler {
880       * reflected by given event ID. The event will be freed immediately to its       * reflected by given event ID. The event will be freed immediately to its
881       * pool and cannot be dereferenced by its old ID anymore. Even if its       * pool and cannot be dereferenced by its old ID anymore. Even if its
882       * allocated back from the Pool later on, it will have a different ID.       * allocated back from the Pool later on, it will have a different ID.
883         *
884         * @param id - unique ID of event to be dropped
885       */       */
886      void AbstractEngineChannel::IgnoreEvent(int id) {      void AbstractEngineChannel::IgnoreEvent(event_id_t id) {
887          RTList<Event>::Iterator it = pEvents->fromID(id);          RTList<Event>::Iterator it = pEvents->fromID(id);
888          if (it) pEvents->free(it);          if (it) pEvents->free(it);
889      }      }
890    
891        /**
892         * Called by real-time instrument script functions to ignore the note
893         * reflected by given note ID. The note's event will be freed immediately
894         * to its event pool and this will prevent voices to be launched for the
895         * note.
896         *
897         * NOTE: preventing a note by calling this method works only if the note
898         * was launched within the current audio fragment cycle.
899         *
900         * @param id - unique ID of note to be dropped
901         */    
902        void AbstractEngineChannel::IgnoreNote(note_id_t id) {
903            NoteBase* pNote = pEngine->NoteByID(id);
904            if (!pNote) return;
905            IgnoreEvent(pNote->eventID);
906        }
907    
908        /** @brief Drop the requested event.
909         *
910         * Called by real-time instrument script functions to ignore the event
911         * reflected by the given event @a id. This method detects whether the
912         * passed ID is actually a @c Note ID or a regular @c Event ID and act
913         * accordingly.
914         *
915         * @param id - event id (from script scope)
916         * @see ScriptID
917         */
918        void AbstractEngineChannel::IgnoreEventByScriptID(const ScriptID& id) {
919            switch (id.type()) {
920                case ScriptID::EVENT:
921                    IgnoreEvent( id.eventID() );
922                    break;
923                case ScriptID::NOTE:
924                    IgnoreNote( id.noteID() );
925                    break;
926            }
927        }
928    
929      FxSend* AbstractEngineChannel::AddFxSend(uint8_t MidiCtrl, String Name) throw (Exception) {      FxSend* AbstractEngineChannel::AddFxSend(uint8_t MidiCtrl, String Name) throw (Exception) {
930          if (pEngine) pEngine->DisableAndLock();          if (pEngine) pEngine->DisableAndLock();
931          FxSend* pFxSend = new FxSend(this, MidiCtrl, Name);          FxSend* pFxSend = new FxSend(this, MidiCtrl, Name);

Legend:
Removed from v.2871  
changed lines
  Added in v.2879

  ViewVC Help
Powered by ViewVC