/[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 2025 by schoenebeck, Sun Nov 1 18:47:59 2009 UTC revision 2326 by persson, Thu Mar 8 19:40:14 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-2009 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009 Grigor Iliev                                       *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   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 49  namespace LinuxSampler { Line 49  namespace LinuxSampler {
49      }      }
50    
51      AbstractEngineChannel::~AbstractEngineChannel() {      AbstractEngineChannel::~AbstractEngineChannel() {
52                    delete pEventQueue;
53          if (pEventQueue) delete pEventQueue;          DeleteGroupEventLists();
54          RemoveAllFxSends();          RemoveAllFxSends();
55      }      }
56    
# Line 191  namespace LinuxSampler { Line 191  namespace LinuxSampler {
191          return (pEngine) ? pEngine->pAudioOutputDevice : NULL;          return (pEngine) ? pEngine->pAudioOutputDevice : NULL;
192      }      }
193    
194        /**
195         * Gets thread safe access to the currently connected audio output
196         * device from other threads than the lscp thread.
197         */
198        AudioOutputDevice* AbstractEngineChannel::GetAudioOutputDeviceSafe() {
199            EngineMutex.Lock();
200            AudioOutputDevice* res = GetAudioOutputDevice();
201            EngineMutex.Unlock();
202            return res;
203        }
204    
205      void AbstractEngineChannel::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {      void AbstractEngineChannel::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {
206          if (!pEngine || !pEngine->pAudioOutputDevice) throw AudioOutputException("No audio output device connected yet.");          if (!pEngine || !pEngine->pAudioOutputDevice) throw AudioOutputException("No audio output device connected yet.");
207    
# Line 278  namespace LinuxSampler { Line 289  namespace LinuxSampler {
289       *  @param Key      - MIDI key number of the triggered key       *  @param Key      - MIDI key number of the triggered key
290       *  @param Velocity - MIDI velocity value of the triggered key       *  @param Velocity - MIDI velocity value of the triggered key
291       */       */
292      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity) {      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {
293          if (pEngine) {          if (pEngine) {
294              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
295              event.Type                = Event::type_note_on;              event.Type                = Event::type_note_on;
296              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
297              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
298                event.Param.Note.Channel  = MidiChannel;
299              event.pEngineChannel      = this;              event.pEngineChannel      = this;
300              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
301              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 311  namespace LinuxSampler { Line 323  namespace LinuxSampler {
323       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
324       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
325       */       */
326      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, int32_t FragmentPos) {      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel, int32_t FragmentPos) {
327          if (FragmentPos < 0) {          if (FragmentPos < 0) {
328              dmsg(1,("EngineChannel::SendNoteOn(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("EngineChannel::SendNoteOn(): negative FragmentPos! Seems MIDI driver is buggy!"));
329          }          }
# Line 320  namespace LinuxSampler { Line 332  namespace LinuxSampler {
332              event.Type                = Event::type_note_on;              event.Type                = Event::type_note_on;
333              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
334              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
335                event.Param.Note.Channel  = MidiChannel;
336              event.pEngineChannel      = this;              event.pEngineChannel      = this;
337              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
338              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 345  namespace LinuxSampler { Line 358  namespace LinuxSampler {
358       *  @param Key      - MIDI key number of the released key       *  @param Key      - MIDI key number of the released key
359       *  @param Velocity - MIDI release velocity value of the released key       *  @param Velocity - MIDI release velocity value of the released key
360       */       */
361      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity) {      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {
362          if (pEngine) {          if (pEngine) {
363              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
364              event.Type                = Event::type_note_off;              event.Type                = Event::type_note_off;
365              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
366              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
367                event.Param.Note.Channel  = MidiChannel;
368              event.pEngineChannel      = this;              event.pEngineChannel      = this;
369              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
370              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 378  namespace LinuxSampler { Line 392  namespace LinuxSampler {
392       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
393       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
394       */       */
395      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, int32_t FragmentPos) {      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel, int32_t FragmentPos) {
396          if (FragmentPos < 0) {          if (FragmentPos < 0) {
397              dmsg(1,("EngineChannel::SendNoteOff(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("EngineChannel::SendNoteOff(): negative FragmentPos! Seems MIDI driver is buggy!"));
398          }          }
# Line 387  namespace LinuxSampler { Line 401  namespace LinuxSampler {
401              event.Type                = Event::type_note_off;              event.Type                = Event::type_note_off;
402              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
403              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
404                event.Param.Note.Channel  = MidiChannel;
405              event.pEngineChannel      = this;              event.pEngineChannel      = this;
406              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
407              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 411  namespace LinuxSampler { Line 426  namespace LinuxSampler {
426       *       *
427       *  @param Pitch - MIDI pitch value (-8192 ... +8191)       *  @param Pitch - MIDI pitch value (-8192 ... +8191)
428       */       */
429      void AbstractEngineChannel::SendPitchbend(int Pitch) {      void AbstractEngineChannel::SendPitchbend(int Pitch, uint8_t MidiChannel) {
430          if (pEngine) {          if (pEngine) {
431              Event event             = pEngine->pEventGenerator->CreateEvent();              Event event             = pEngine->pEventGenerator->CreateEvent();
432              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
433              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
434                event.Param.Pitch.Channel = MidiChannel;
435              event.pEngineChannel    = this;              event.pEngineChannel    = this;
436              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
437              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 432  namespace LinuxSampler { Line 448  namespace LinuxSampler {
448       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
449       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
450       */       */
451      void AbstractEngineChannel::SendPitchbend(int Pitch, int32_t FragmentPos) {      void AbstractEngineChannel::SendPitchbend(int Pitch, uint8_t MidiChannel, int32_t FragmentPos) {
452          if (FragmentPos < 0) {          if (FragmentPos < 0) {
453              dmsg(1,("AbstractEngineChannel::SendPitchBend(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("AbstractEngineChannel::SendPitchBend(): negative FragmentPos! Seems MIDI driver is buggy!"));
454          }          }
# Line 440  namespace LinuxSampler { Line 456  namespace LinuxSampler {
456              Event event             = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event             = pEngine->pEventGenerator->CreateEvent(FragmentPos);
457              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
458              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
459                event.Param.Pitch.Channel = MidiChannel;
460              event.pEngineChannel    = this;              event.pEngineChannel    = this;
461              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
462              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 455  namespace LinuxSampler { Line 472  namespace LinuxSampler {
472       *  @param Controller - MIDI controller number of the occured control change       *  @param Controller - MIDI controller number of the occured control change
473       *  @param Value      - value of the control change       *  @param Value      - value of the control change
474       */       */
475      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value) {      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, uint8_t MidiChannel) {
476          if (pEngine) {          if (pEngine) {
477              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
478              event.Type                = Event::type_control_change;              event.Type                = Event::type_control_change;
479              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
480              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
481                event.Param.CC.Channel    = MidiChannel;
482              event.pEngineChannel      = this;              event.pEngineChannel      = this;
483              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
484              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 478  namespace LinuxSampler { Line 496  namespace LinuxSampler {
496       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
497       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
498       */       */
499      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, int32_t FragmentPos) {      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, uint8_t MidiChannel, int32_t FragmentPos) {
500          if (FragmentPos < 0) {          if (FragmentPos < 0) {
501              dmsg(1,("AbstractEngineChannel::SendControlChange(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("AbstractEngineChannel::SendControlChange(): negative FragmentPos! Seems MIDI driver is buggy!"));
502          }          }
# Line 487  namespace LinuxSampler { Line 505  namespace LinuxSampler {
505              event.Type                = Event::type_control_change;              event.Type                = Event::type_control_change;
506              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
507              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
508                event.Param.CC.Channel    = MidiChannel;
509              event.pEngineChannel      = this;              event.pEngineChannel      = this;
510              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
511              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 510  namespace LinuxSampler { Line 529  namespace LinuxSampler {
529          // import events from pure software MIDI "devices"          // import events from pure software MIDI "devices"
530          // (e.g. virtual keyboard in instrument editor)          // (e.g. virtual keyboard in instrument editor)
531          {          {
532                const uint8_t channel = MidiChannel() == midi_chan_all ? 0 : MidiChannel();
533              const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices              const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices
534              Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);
535              VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device              VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device
# Line 527  namespace LinuxSampler { Line 547  namespace LinuxSampler {
547                              event.Type = Event::type_note_on;                              event.Type = Event::type_note_on;
548                              event.Param.Note.Key      = devEvent.Arg1;                              event.Param.Note.Key      = devEvent.Arg1;
549                              event.Param.Note.Velocity = devEvent.Arg2;                              event.Param.Note.Velocity = devEvent.Arg2;
550                                event.Param.Note.Channel  = channel;
551                              break;                              break;
552                          case VirtualMidiDevice::EVENT_TYPE_NOTEOFF:                          case VirtualMidiDevice::EVENT_TYPE_NOTEOFF:
553                              event.Type = Event::type_note_off;                              event.Type = Event::type_note_off;
554                              event.Param.Note.Key      = devEvent.Arg1;                              event.Param.Note.Key      = devEvent.Arg1;
555                              event.Param.Note.Velocity = devEvent.Arg2;                              event.Param.Note.Velocity = devEvent.Arg2;
556                                event.Param.Note.Channel  = channel;
557                              break;                              break;
558                          case VirtualMidiDevice::EVENT_TYPE_CC:                          case VirtualMidiDevice::EVENT_TYPE_CC:
559                              event.Type = Event::type_control_change;                              event.Type = Event::type_control_change;
560                              event.Param.CC.Controller = devEvent.Arg1;                              event.Param.CC.Controller = devEvent.Arg1;
561                              event.Param.CC.Value      = devEvent.Arg2;                              event.Param.CC.Value      = devEvent.Arg2;
562                                event.Param.CC.Channel    = channel;
563                              break;                              break;
564                          default:                          default:
565                              std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type ("                              std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type ("
# Line 661  namespace LinuxSampler { Line 684  namespace LinuxSampler {
684          if (pEngine) pEngine->Enable();          if (pEngine) pEngine->Enable();
685      }      }
686    
687        /**
688         * Add a group number to the set of key groups. Should be called
689         * when an instrument is loaded to make sure there are event lists
690         * for all key groups.
691         */
692        void AbstractEngineChannel::AddGroup(uint group) {
693            if (group) {
694                std::pair<ActiveKeyGroupMap::iterator, bool> p =
695                    ActiveKeyGroups.insert(ActiveKeyGroupMap::value_type(group, 0));
696                if (p.second) {
697                    // If the engine channel is pending deletion (see bug
698                    // #113), pEngine will be null, so we can't use
699                    // pEngine->pEventPool here. Instead we're using a
700                    // specialized RTList that allows specifying the pool
701                    // later.
702                    (*p.first).second = new LazyList<Event>;
703                }
704            }
705        }
706    
707        /**
708         * Handle key group (a.k.a. exclusive group) conflicts.
709         */
710        void AbstractEngineChannel::HandleKeyGroupConflicts(uint KeyGroup, Pool<Event>::Iterator& itNoteOnEvent) {
711            dmsg(4,("HandelKeyGroupConflicts KeyGroup=%d\n", KeyGroup));
712            if (KeyGroup) {
713                // send a release event to all active voices in the group
714                RTList<Event>::Iterator itEvent = ActiveKeyGroups[KeyGroup]->allocAppend(pEngine->pEventPool);
715                *itEvent = *itNoteOnEvent;
716            }
717        }
718    
719        /**
720         * Empty the lists of group events. Should be called from the
721         * audio thread, after all voices have been rendered.
722         */
723        void AbstractEngineChannel::ClearGroupEventLists() {
724            for (ActiveKeyGroupMap::iterator iter = ActiveKeyGroups.begin();
725                 iter != ActiveKeyGroups.end(); iter++) {
726                if (iter->second) {
727                    iter->second->clear();
728                } else {
729                    dmsg(1,("EngineChannel: group event list was NULL"));
730                }
731            }
732        }
733    
734        /**
735         * Remove all lists with group events.
736         */
737        void AbstractEngineChannel::DeleteGroupEventLists() {
738            for (ActiveKeyGroupMap::iterator iter = ActiveKeyGroups.begin();
739                 iter != ActiveKeyGroups.end(); iter++) {
740                delete iter->second;
741            }
742            ActiveKeyGroups.clear();
743        }
744    
745  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2025  
changed lines
  Added in v.2326

  ViewVC Help
Powered by ViewVC