/[svn]/linuxsampler/trunk/src/engines/EngineBase.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/EngineBase.h

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

revision 2043 by persson, Sat Jan 9 09:37:01 2010 UTC revision 2162 by persson, Tue Feb 8 18:22:50 2011 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-2011 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 190  namespace LinuxSampler { Line 190  namespace LinuxSampler {
190                  // been deleted by the disk thread                  // been deleted by the disk thread
191                  if (iPendingStreamDeletions) ProcessPendingStreamDeletions();                  if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
192    
193                    // Release the instrument change command. (This has to
194                    // be done after all voices have been rendered and not
195                    // in HandleInstrumentChanges, as the RegionsInUse
196                    // list has been built up by the voice renderers.)
197                    for (int i = 0; i < engineChannels.size(); i++) {
198                        EngineChannelBase<V, R, I>* channel =
199                            static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);
200                        channel->InstrumentChangeCommandReader.Unlock();
201                    }
202                  FrameTime += Samples;                  FrameTime += Samples;
203    
204                  EngineDisabled.RttDone();                  EngineDisabled.RttDone();
# Line 299  namespace LinuxSampler { Line 308  namespace LinuxSampler {
308                      // lower minimum release time                      // lower minimum release time
309                      const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;                      const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
310                      for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {                      for (VoiceIterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
311                          iterVoice->EG1.CalculateFadeOutCoeff(minReleaseTime, SampleRate);                          iterVoice->pEG1->CalculateFadeOutCoeff(minReleaseTime, SampleRate);
312                      }                      }
313                      pVoicePool->clear();                      pVoicePool->clear();
314                  }                  }
# Line 339  namespace LinuxSampler { Line 348  namespace LinuxSampler {
348                      }                      }
349                  }                  }
350                  pVoicePool->clear();                  pVoicePool->clear();
351                    
352                    // (re)create dedicated voice audio buffers
353                    //TODO: we could optimize resource usage a bit by just allocating these dedicated voice buffers when there is at least one engine channel with FX sends, because only in this case those special buffers are used actually, but since it would usually only save couple bytes in total, its probably not worth it
354                    if (pDedicatedVoiceChannelLeft)  delete pDedicatedVoiceChannelLeft;
355                    if (pDedicatedVoiceChannelRight) delete pDedicatedVoiceChannelRight;
356                    pDedicatedVoiceChannelLeft  = new AudioChannel(0, MaxSamplesPerCycle);
357                    pDedicatedVoiceChannelRight = new AudioChannel(1, MaxSamplesPerCycle);
358              }              }
359    
360              /**              /**
# Line 530  namespace LinuxSampler { Line 546  namespace LinuxSampler {
546    
547              //friend class EngineChannelBase<V, R, I>;              //friend class EngineChannelBase<V, R, I>;
548    
549                static IM instruments;
550    
551          protected:          protected:
552              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {              class SuspensionVoiceHandler : public MidiKeyboardManager<V>::VoiceHandler {
553              public:              public:
# Line 558  namespace LinuxSampler { Line 576  namespace LinuxSampler {
576                  }                  }
577              };              };
578    
             static IM instruments;  
   
579              Pool<R*>* pRegionPool[2]; ///< Double buffered pool, used by the engine channels to keep track of regions in use.              Pool<R*>* pRegionPool[2]; ///< Double buffered pool, used by the engine channels to keep track of regions in use.
580              int       MinFadeOutSamples;     ///< The number of samples needed to make an instant fade out (e.g. for voice stealing) without leading to clicks.              int       MinFadeOutSamples;     ///< The number of samples needed to make an instant fade out (e.g. for voice stealing) without leading to clicks.
581              D*        pDiskThread;              D*        pDiskThread;
# Line 765  namespace LinuxSampler { Line 781  namespace LinuxSampler {
781                      //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions                      //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions
782                      ResetSuspendedRegions();                      ResetSuspendedRegions();
783                  }                  }
   
                 for (int i = 0; i < engineChannels.size(); i++) {  
                     EngineChannelBase<V, R, I>* channel =  
                         static_cast<EngineChannelBase<V, R, I>*>(engineChannels[i]);  
                     channel->InstrumentChangeCommandReader.Unlock();  
                 }  
784              }              }
785    
786              /**              /**
# Line 857  namespace LinuxSampler { Line 867  namespace LinuxSampler {
867                  pChannel->ClearEventLists();                  pChannel->ClearEventLists();
868              }              }
869    
870                /**
871                 * Process MIDI control change events with hard coded behavior,
872                 * that is controllers whose behavior is defined independently
873                 * of the actual sampler engine type and instrument.
874                 *
875                 * @param pEngineChannel - engine channel on which the MIDI CC event was received
876                 * @param itControlChangeEvent - the actual MIDI CC event
877                 */
878              void ProcessHardcodedControllers (              void ProcessHardcodedControllers (
879                  EngineChannel*          pEngineChannel,                  EngineChannel*          pEngineChannel,
880                  Pool<Event>::Iterator&  itControlChangeEvent                  Pool<Event>::Iterator&  itControlChangeEvent
# Line 869  namespace LinuxSampler { Line 887  namespace LinuxSampler {
887                          pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;                          pChannel->PortamentoTime = (float) itControlChangeEvent->Param.CC.Value / 127.0f * (float) CONFIG_PORTAMENTO_TIME_MAX + (float) CONFIG_PORTAMENTO_TIME_MIN;
888                          break;                          break;
889                      }                      }
890                      case 6: { // data entry (currently only used for RPN controllers)                      case 6: { // data entry (currently only used for RPN and NRPN controllers)
891                          if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones                          //dmsg(1,("DATA ENTRY %d\n", itControlChangeEvent->Param.CC.Value));
892                              int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;                          if (pChannel->GetMidiRpnController() >= 0) { // RPN controller number was sent previously ...
893                              // limit to +- two octaves for now                              dmsg(4,("Guess it's an RPN ...\n"));
894                              transpose = RTMath::Min(transpose,  24);                              if (pChannel->GetMidiRpnController() == 2) { // coarse tuning in half tones
895                              transpose = RTMath::Max(transpose, -24);                                  int transpose = (int) itControlChangeEvent->Param.CC.Value - 64;
896                              pChannel->GlobalTranspose = transpose;                                  // limit to +- two octaves for now
897                              // workaround, so we won't have hanging notes                                  transpose = RTMath::Min(transpose,  24);
898                              pChannel->ReleaseAllVoices(itControlChangeEvent);                                  transpose = RTMath::Max(transpose, -24);
899                                    pChannel->GlobalTranspose = transpose;
900                                    // workaround, so we won't have hanging notes
901                                    pChannel->ReleaseAllVoices(itControlChangeEvent);
902                                }
903                                // to prevent other MIDI CC #6 messages to be misenterpreted as RPN controller data
904                                pChannel->ResetMidiRpnController();
905                            } else if (pChannel->GetMidiNrpnController() >= 0) { // NRPN controller number was sent previously ...
906                                dmsg(4,("Guess it's an NRPN ...\n"));
907                                const int NrpnCtrlMSB = pChannel->GetMidiNrpnController() >> 8;
908                                const int NrpnCtrlLSB = pChannel->GetMidiNrpnController() & 0xff;
909                                dmsg(4,("NRPN MSB=%d LSB=%d Data=%d\n", NrpnCtrlMSB, NrpnCtrlLSB, itControlChangeEvent->Param.CC.Value));
910                                switch (NrpnCtrlMSB) {
911                                    case 0x1a: { // volume level of note (Roland GS NRPN)
912                                        const uint note = NrpnCtrlLSB;
913                                        const uint vol  = itControlChangeEvent->Param.CC.Value;
914                                        dmsg(4,("Note Volume NRPN received (note=%d,vol=%d).\n", note, vol));
915                                        if (note < 128 && vol < 128)
916                                            pChannel->pMIDIKeyInfo[note].Volume = VolumeCurve[vol];
917                                        break;
918                                    }
919                                    case 0x1c: { // panpot of note (Roland GS NRPN)
920                                        const uint note = NrpnCtrlLSB;
921                                        const uint pan  = itControlChangeEvent->Param.CC.Value;
922                                        dmsg(4,("Note Pan NRPN received (note=%d,pan=%d).\n", note, pan));
923                                        if (note < 128 && pan < 128) {
924                                            pChannel->pMIDIKeyInfo[note].PanLeft  = PanCurve[128 - pan];
925                                            pChannel->pMIDIKeyInfo[note].PanRight = PanCurve[pan];
926                                        }
927                                        break;
928                                    }
929                                    case 0x1d: { // reverb send of note (Roland GS NRPN)
930                                        const uint note = NrpnCtrlLSB;
931                                        const float reverb = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
932                                        dmsg(4,("Note Reverb Send NRPN received (note=%d,send=%d).\n", note, reverb));
933                                        if (note < 128)
934                                            pChannel->pMIDIKeyInfo[note].ReverbSend = reverb;
935                                        break;
936                                    }
937                                    case 0x1e: { // chorus send of note (Roland GS NRPN)
938                                        const uint note = NrpnCtrlLSB;
939                                        const float chorus = float(itControlChangeEvent->Param.CC.Value) / 127.0f;
940                                        dmsg(4,("Note Chorus Send NRPN received (note=%d,send=%d).\n", note, chorus));
941                                        if (note < 128)
942                                            pChannel->pMIDIKeyInfo[note].ChorusSend = chorus;
943                                        break;
944                                    }
945                                }
946                                // to prevent other MIDI CC #6 messages to be misenterpreted as NRPN controller data
947                                pChannel->ResetMidiNrpnController();
948                          }                          }
                         // to avoid other MIDI CC #6 messages to be misenterpreted as RPN controller data  
                         pChannel->ResetMidiRpnController();  
949                          break;                          break;
950                      }                      }
951                      case 7: { // volume                      case 7: { // volume
# Line 969  namespace LinuxSampler { Line 1034  namespace LinuxSampler {
1034                          }                          }
1035                          break;                          break;
1036                      }                      }
1037                        case 98: { // NRPN controller LSB
1038                            dmsg(4,("NRPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1039                            pEngineChannel->SetMidiNrpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1040                            break;
1041                        }
1042                        case 99: { // NRPN controller MSB
1043                            dmsg(4,("NRPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1044                            pEngineChannel->SetMidiNrpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1045                            break;
1046                        }
1047                      case 100: { // RPN controller LSB                      case 100: { // RPN controller LSB
1048                            dmsg(4,("RPN LSB %d\n", itControlChangeEvent->Param.CC.Value));
1049                          pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);                          pEngineChannel->SetMidiRpnControllerLsb(itControlChangeEvent->Param.CC.Value);
1050                          break;                          break;
1051                      }                      }
1052                      case 101: { // RPN controller MSB                      case 101: { // RPN controller MSB
1053                            dmsg(4,("RPN MSB %d\n", itControlChangeEvent->Param.CC.Value));
1054                          pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);                          pEngineChannel->SetMidiRpnControllerMsb(itControlChangeEvent->Param.CC.Value);
1055                          break;                          break;
1056                      }                      }
# Line 1064  namespace LinuxSampler { Line 1141  namespace LinuxSampler {
1141                              VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();                              VoiceIterator itVoiceToBeKilled = pOtherKey->pActiveVoices->first();
1142                              VoiceIterator end               = pOtherKey->pActiveVoices->end();                              VoiceIterator end               = pOtherKey->pActiveVoices->end();
1143                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1144                                  if (itVoiceToBeKilled->Type != Voice::type_release_trigger)                                  if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1145                                      itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);                                      itVoiceToBeKilled->Kill(itNoteOnEventOnKeyList);
1146                              }                              }
1147                          }                          }
# Line 1201  namespace LinuxSampler { Line 1278  namespace LinuxSampler {
1278                              VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();                              VoiceIterator itVoiceToBeKilled = pKey->pActiveVoices->first();
1279                              VoiceIterator end               = pKey->pActiveVoices->end();                              VoiceIterator end               = pKey->pActiveVoices->end();
1280                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {                              for (; itVoiceToBeKilled != end; ++itVoiceToBeKilled) {
1281                                  if (itVoiceToBeKilled->Type != Voice::type_release_trigger)                                  if (!(itVoiceToBeKilled->Type & Voice::type_release_trigger))
1282                                      itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);                                      itVoiceToBeKilled->Kill(itNoteOffEventOnKeyList);
1283                              }                              }
1284                          }                          }
# Line 1334  namespace LinuxSampler { Line 1411  namespace LinuxSampler {
1411                              pKey->itSelf = pChannel->pActiveKeys->allocAppend();                              pKey->itSelf = pChannel->pActiveKeys->allocAppend();
1412                              *pKey->itSelf = itNoteOnEvent->Param.Note.Key;                              *pKey->itSelf = itNoteOnEvent->Param.Note.Key;
1413                          }                          }
1414                          if (itNewVoice->KeyGroup) {                          if (itNewVoice->Type & Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)
                             uint** ppKeyGroup = &pChannel->ActiveKeyGroups[itNewVoice->KeyGroup];  
                             *ppKeyGroup = &*pKey->itSelf; // put key as the (new) active key to its key group  
                         }  
                         if (itNewVoice->Type == Voice::type_release_trigger_required) pKey->ReleaseTrigger = true; // mark key for the need of release triggered voice(s)  
1415                          return 0; // success                          return 0; // success
1416                      }                      }
1417                  }                  }

Legend:
Removed from v.2043  
changed lines
  Added in v.2162

  ViewVC Help
Powered by ViewVC