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

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

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

revision 1700 by persson, Sun Feb 17 12:40:59 2008 UTC revision 1762 by schoenebeck, Fri Aug 29 17:33:02 2008 UTC
# Line 358  namespace LinuxSampler { namespace gig { Line 358  namespace LinuxSampler { namespace gig {
358          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();          this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();
359          this->SampleRate         = pAudioOutputDevice->SampleRate();          this->SampleRate         = pAudioOutputDevice->SampleRate();
360    
361          // FIXME: audio drivers with varying fragment sizes might be a problem here          MinFadeOutSamples = int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;
362          MaxFadeOutPos = MaxSamplesPerCycle - int(double(SampleRate) * CONFIG_EG_MIN_RELEASE_TIME) - 1;          if (MaxSamplesPerCycle < MinFadeOutSamples) {
         if (MaxFadeOutPos < 0) {  
363              std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "              std::cerr << "gig::Engine: WARNING, CONFIG_EG_MIN_RELEASE_TIME "
364                        << "too big for current audio fragment size & sampling rate! "                        << "too big for current audio fragment size & sampling rate! "
365                        << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;                        << "May lead to click sounds if voice stealing chimes in!\n" << std::flush;
366              // force volume ramp downs at the beginning of each fragment              // force volume ramp downs at the beginning of each fragment
367              MaxFadeOutPos = 0;              MinFadeOutSamples = MaxSamplesPerCycle;
368              // lower minimum release time              // lower minimum release time
369              const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;              const float minReleaseTime = (float) MaxSamplesPerCycle / (float) SampleRate;
370              for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {              for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
# Line 857  namespace LinuxSampler { namespace gig { Line 856  namespace LinuxSampler { namespace gig {
856       *                         this audio fragment cycle       *                         this audio fragment cycle
857       */       */
858      void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {      void Engine::RouteAudio(EngineChannel* pEngineChannel, uint Samples) {
859          // route master signal          // route dry signal
860          {          {
861              AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);              AudioChannel* pDstL = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelLeft);
862              AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);              AudioChannel* pDstR = pAudioOutputDevice->Channel(pEngineChannel->AudioDeviceChannelRight);
# Line 868  namespace LinuxSampler { namespace gig { Line 867  namespace LinuxSampler { namespace gig {
867          {          {
868              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
869                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
870                  // left channel                  for (int iChan = 0; iChan < 2; ++iChan) {
871                  const int iDstL = pFxSend->DestinationChannel(0);                      AudioChannel* pSource =
872                  if (iDstL < 0) {                          (iChan)
873                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));                              ? pEngineChannel->pChannelRight
874                  } else {                              : pEngineChannel->pChannelLeft;
875                      AudioChannel* pDstL = pAudioOutputDevice->Channel(iDstL);                      const int iDstChan = pFxSend->DestinationChannel(iChan);
876                      if (!pDstL) {                      if (iDstChan < 0) {
877                          dmsg(1,("Engine::RouteAudio() Error: invalid FX send (L) destination channel"));                          dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
878                      } else pEngineChannel->pChannelLeft->MixTo(pDstL, Samples, pFxSend->Level());                          goto channel_cleanup;
879                  }                      }
880                  // right channel                      AudioChannel* pDstChan = NULL;
881                  const int iDstR = pFxSend->DestinationChannel(1);                      if (pFxSend->DestinationMasterEffectChain() >= 0) { // fx send routed to an internal master effect
882                  if (iDstR < 0) {                          EffectChain* pEffectChain =
883                      dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));                              pAudioOutputDevice->MasterEffectChain(
884                  } else {                                  pFxSend->DestinationMasterEffectChain()
885                      AudioChannel* pDstR = pAudioOutputDevice->Channel(iDstR);                              );
886                      if (!pDstR) {                          if (!pEffectChain) {
887                          dmsg(1,("Engine::RouteAudio() Error: invalid FX send (R) destination channel"));                              dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffectChain()));
888                      } else pEngineChannel->pChannelRight->MixTo(pDstR, Samples, pFxSend->Level());                              goto channel_cleanup;
889                            }
890                            Effect* pEffect =
891                                pEffectChain->GetEffect(
892                                    pFxSend->DestinationMasterEffect()
893                                );
894                            if (!pEffect) {
895                                dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination effect %d of effect chain %d", ((iChan) ? "R" : "L"), pFxSend->DestinationMasterEffect(), pFxSend->DestinationMasterEffectChain()));
896                                goto channel_cleanup;
897                            }
898                            pDstChan = pEffect->InputChannel(iDstChan);
899                        } else { // FX send routed directly to an audio output channel
900                            pDstChan = pAudioOutputDevice->Channel(iDstChan);
901                        }
902                        if (!pDstChan) {
903                            dmsg(1,("Engine::RouteAudio() Error: invalid FX send (%s) destination channel (%d->%d)", ((iChan) ? "R" : "L"), iChan, iDstChan));
904                            goto channel_cleanup;
905                        }
906                        pSource->MixTo(pDstChan, Samples, pFxSend->Level());
907                  }                  }
908              }              }
909          }          }
910            channel_cleanup:
911          // reset buffers with silence (zero out) for the next audio cycle          // reset buffers with silence (zero out) for the next audio cycle
912          pEngineChannel->pChannelLeft->Clear();          pEngineChannel->pChannelLeft->Clear();
913          pEngineChannel->pChannelRight->Clear();          pEngineChannel->pChannelRight->Clear();
# Line 935  namespace LinuxSampler { namespace gig { Line 953  namespace LinuxSampler { namespace gig {
953       *       *
954       *  @param pData - pointer to sysex data       *  @param pData - pointer to sysex data
955       *  @param Size  - lenght of sysex data (in bytes)       *  @param Size  - lenght of sysex data (in bytes)
956         *  @param pSender - the MIDI input port on which the SysEx message was
957         *                   received
958       */       */
959      void Engine::SendSysex(void* pData, uint Size) {      void Engine::SendSysex(void* pData, uint Size, MidiInputPort* pSender) {
960          Event event             = pEventGenerator->CreateEvent();          Event event             = pEventGenerator->CreateEvent();
961          event.Type              = Event::type_sysex;          event.Type              = Event::type_sysex;
962          event.Param.Sysex.Size  = Size;          event.Param.Sysex.Size  = Size;
963          event.pEngineChannel    = NULL; // as Engine global event          event.pEngineChannel    = NULL; // as Engine global event
964            event.pMidiInputPort    = pSender;
965          if (pEventQueue->write_space() > 0) {          if (pEventQueue->write_space() > 0) {
966              if (pSysexBuffer->write_space() >= Size) {              if (pSysexBuffer->write_space() >= Size) {
967                  // copy sysex data to input buffer                  // copy sysex data to input buffer
# Line 1709  namespace LinuxSampler { namespace gig { Line 1730  namespace LinuxSampler { namespace gig {
1730                  //TODO: not sample accurate yet                  //TODO: not sample accurate yet
1731                  pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];                  pEngineChannel->GlobalPanLeft  = PanCurve[128 - itControlChangeEvent->Param.CC.Value];
1732                  pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];                  pEngineChannel->GlobalPanRight = PanCurve[itControlChangeEvent->Param.CC.Value];
1733                    pEngineChannel->iLastPanRequest = itControlChangeEvent->Param.CC.Value;
1734                  break;                  break;
1735              }              }
1736              case 64: { // sustain              case 64: { // sustain
# Line 1849  namespace LinuxSampler { namespace gig { Line 1871  namespace LinuxSampler { namespace gig {
1871          if (!pEngineChannel->fxSends.empty()) {          if (!pEngineChannel->fxSends.empty()) {
1872              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {              for (int iFxSend = 0; iFxSend < pEngineChannel->GetFxSendCount(); iFxSend++) {
1873                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);                  FxSend* pFxSend = pEngineChannel->GetFxSend(iFxSend);
1874                  if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller)                  if (pFxSend->MidiController() == itControlChangeEvent->Param.CC.Controller) {
1875                      pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);                      pFxSend->SetLevel(itControlChangeEvent->Param.CC.Value);
1876                      pFxSend->SetInfoChanged(true);                      pFxSend->SetInfoChanged(true);
1877                    }
1878              }              }
1879          }          }
1880      }      }
# Line 1870  namespace LinuxSampler { namespace gig { Line 1893  namespace LinuxSampler { namespace gig {
1893          if (exclusive_status != 0xF0)       goto free_sysex_data;          if (exclusive_status != 0xF0)       goto free_sysex_data;
1894    
1895          switch (id) {          switch (id) {
1896                case 0x7f: { // (Realtime) Universal Sysex (GM Standard)
1897                    uint8_t sysex_channel, sub_id1, sub_id2, val_msb, val_lsb;;
1898                    if (!reader.pop(&sysex_channel)) goto free_sysex_data;
1899                    if (!reader.pop(&sub_id1)) goto free_sysex_data;
1900                    if (!reader.pop(&sub_id2)) goto free_sysex_data;
1901                    if (!reader.pop(&val_lsb)) goto free_sysex_data;
1902                    if (!reader.pop(&val_msb)) goto free_sysex_data;
1903                    //TODO: for now we simply ignore the sysex channel, seldom used anyway
1904                    switch (sub_id1) {
1905                        case 0x04: // Device Control
1906                            switch (sub_id2) {
1907                                case 0x01: { // Master Volume
1908                                    const double volume =
1909                                        double((uint(val_msb)<<7) | uint(val_lsb)) / 16383.0;
1910                                    #if CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1911                                    // apply volume to all sampler channels that
1912                                    // are connected to the same MIDI input port
1913                                    // this sysex message arrived on
1914                                    for (int i = 0; i < engineChannels.size(); ++i) {
1915                                        EngineChannel* pEngineChannel = engineChannels[i];
1916                                        if (pEngineChannel->GetMidiInputPort() ==
1917                                            itSysexEvent->pMidiInputPort)
1918                                        {
1919                                            pEngineChannel->Volume(volume);
1920                                        }
1921                                    }
1922                                    #else
1923                                    // apply volume globally to the whole sampler
1924                                    GLOBAL_VOLUME = volume;
1925                                    #endif // CONFIG_MASTER_VOLUME_SYSEX_BY_PORT
1926                                    break;
1927                                }
1928                            }
1929                            break;
1930                    }
1931                    break;
1932                }
1933              case 0x41: { // Roland              case 0x41: { // Roland
1934                  dmsg(3,("Roland Sysex\n"));                  dmsg(3,("Roland Sysex\n"));
1935                  uint8_t device_id, model_id, cmd_id;                  uint8_t device_id, model_id, cmd_id;
# Line 1906  namespace LinuxSampler { namespace gig { Line 1966  namespace LinuxSampler { namespace gig {
1966                              dmsg(3,("\t\t\tNew scale applied.\n"));                              dmsg(3,("\t\t\tNew scale applied.\n"));
1967                              break;                              break;
1968                          }                          }
1969                            case 0x15: { // chromatic / drumkit mode
1970                                dmsg(3,("\t\tMIDI Instrument Map Switch\n"));
1971                                uint8_t part = addr[1] & 0x0f;
1972                                uint8_t map;
1973                                if (!reader.pop(&map)) goto free_sysex_data;
1974                                for (int i = 0; i < engineChannels.size(); ++i) {
1975                                    EngineChannel* pEngineChannel = engineChannels[i];
1976                                    if (
1977                                        (pEngineChannel->midiChannel == part ||
1978                                         pEngineChannel->midiChannel == midi_chan_all) &&
1979                                         pEngineChannel->GetMidiInputPort() == itSysexEvent->pMidiInputPort
1980                                    ) {
1981                                        try {
1982                                            pEngineChannel->SetMidiInstrumentMap(map);
1983                                        } catch (Exception e) {
1984                                            dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d: %s\n", map, part, e.Message().c_str()));
1985                                            goto free_sysex_data;
1986                                        } catch (...) {
1987                                            dmsg(2,("\t\t\tCould not apply MIDI instrument map %d to part %d (unknown exception)\n", map, part));
1988                                            goto free_sysex_data;
1989                                        }
1990                                    }
1991                                }
1992                                dmsg(3,("\t\t\tApplied MIDI instrument map %d to part %d.\n", map, part));
1993                                break;
1994                            }
1995                      }                      }
1996                  }                  }
1997                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)                  else if (addr[0] == 0x40 && (addr[1] & 0xf0) == 0x20) { // Part Parameters (2)
# Line 2048  namespace LinuxSampler { namespace gig { Line 2134  namespace LinuxSampler { namespace gig {
2134      }      }
2135    
2136      String Engine::Version() {      String Engine::Version() {
2137          String s = "$Revision: 1.88 $";          String s = "$Revision: 1.96 $";
2138          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
2139      }      }
2140    

Legend:
Removed from v.1700  
changed lines
  Added in v.1762

  ViewVC Help
Powered by ViewVC