bool IPlugStandalone::SendMidiMsg(IMidiMsg* pMsg)
{
  #ifdef OS_IOS
  mIOSLink->SendMidiMsg(pMsg);
  #else
  if (DoesMIDI())
  {
    IMidiMsg newMsg = *pMsg;

    // if the midi channel out filter is set, reassign the status byte appropriately
    if (!*mMidiOutChan == 0)
    {
      newMsg.mStatus = (*mMidiOutChan)-1 | ((unsigned int) newMsg.StatusMsg() << 4) ;
    }

    std::vector<unsigned char> message;
    message.push_back( newMsg.mStatus );
    message.push_back( newMsg.mData1 );
    message.push_back( newMsg.mData2 );

    mMidiOut->sendMessage( &message );
    return true;
  }
  #endif
  return false;
}
Exemple #2
0
void MIDIReceiver::advance() {
  while (!mMidiQueue.Empty()) {
    IMidiMsg* midiMessage = mMidiQueue.Peek();
    if (midiMessage->mOffset > mOffset) break;

    IMidiMsg::EStatusMsg status = midiMessage->StatusMsg();
    int noteNumber = midiMessage->NoteNumber();
    int velocity = midiMessage->Velocity();
    // There are only note on/off messages in the queue, see ::OnMessageReceived
    if (status == IMidiMsg::kNoteOn && velocity) {
      if (mKeyStatus[noteNumber] == false) {
        mKeyStatus[noteNumber] = true;
        mNumKeys += 1;
        noteOn(noteNumber, velocity);
      }
    }
    else {
      if (mKeyStatus[noteNumber] == true) {
        mKeyStatus[noteNumber] = false;
        mNumKeys -= 1;
        noteOff(noteNumber, velocity);
      }
    }
    mMidiQueue.Remove();
  }
  mOffset++;
}
Exemple #3
0
//  We're only ever playing one note (monophonic)
void Arponaut::NoteOff()
{
    if (playing_.StatusMsg() != IMidiMsg::kNoteOff) {
        IMidiMsg offMsg;
        offMsg.MakeNoteOffMsg(playing_.NoteNumber(), playing_.mOffset);
        SendMidiMsg(&offMsg);
        playing_ = offMsg;
    }
}
Exemple #4
0
void Arponaut::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
    // Mutex is already locked for us.
    ENoteLength noteLength = (ENoteLength) ((int(GetParam(kNoteLength)->Value())) + 1);
    EOctaves    octaves    = (EOctaves)    ((int(GetParam(kOctaves)->Value())) + 1);
    EArpMode    arpMode    = (EArpMode)    (int(GetParam(kArpMode)->Value()));
    EInsertMode insertMode = (EInsertMode) (int(GetParam(kInsertMode)->Value()));

    if (GetGUI()) {
        //GetGUI()->SetControlFromPlug(mMeterIdx_L, peakL);
        //GetGUI()->SetControlFromPlug(mMeterIdx_R, peakR);
    }

    int pos = GetSamplePos();
    running_ = (pos != lastPos_);
    int tnum, tden;
    GetTimeSig(&tnum, &tden);

    if (keymap_.held() == 0) {
        NoteOff(); // only sent if a note is already playing
    }
    
    if (running_ && keymap_.held()) {
        sequence_->setOctaves(octaves);
        sequence_->setArpMode(arpMode);
        sequence_->setInsertMode(insertMode);

        double perBeat = GetSamplesPerBeat() / noteLength;
        // trigger?
        int ibar = static_cast<int>(double(pos) / perBeat);
        int ilastBar = static_cast<int>(double(lastPos_) / perBeat);

        if ((pos == 0 && ibar == 0) || (ibar != ilastBar)) {
            // Log("pos %d pb %f Num %d Den %d ibar %d lastbar %d\n", pos, perBeat, tnum, tden, ibar, ilastBar);
            NoteOff();
            IMidiMsg* next = sequence_->next();

            if (next && next->StatusMsg() == IMidiMsg::kNoteOn) {
                SendMidiMsg(next);
                playing_ = *next;
            }

            matrix->SetDirty(false);
        }
    }

    lastPos_ = pos;
}
Exemple #5
0
void Synthesis::processVirtualKeyboard() {
    IKeyboardControl* virtualKeyboard = (IKeyboardControl*) mVirtualKeyboard;
    int virtualKeyboardNoteNumber = virtualKeyboard->GetKey() + virtualKeyboardMinimumNoteNumber;

    if(lastVirtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) {
        // The note number has changed from a valid key to something else (valid key or nothing). Release the valid key:
        IMidiMsg midiMessage;
        midiMessage.MakeNoteOffMsg(lastVirtualKeyboardNoteNumber, 0);
        mMIDIReceiver.onMessageReceived(&midiMessage);
    }

    if (virtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) {
        // A valid key is pressed that wasn't pressed the previous call. Send a "note on" message to the MIDI receiver:
        IMidiMsg midiMessage;
        midiMessage.MakeNoteOnMsg(virtualKeyboardNoteNumber, virtualKeyboard->GetVelocity(), 0);
        mMIDIReceiver.onMessageReceived(&midiMessage);
    }

    lastVirtualKeyboardNoteNumber = virtualKeyboardNoteNumber;
}
Exemple #6
0
void Vega::processVirtualKeyboard() {
  IKeyboardControl* virtualKeyboard = (IKeyboardControl*) mVirtualKeyboard;
  int virtualKeyboardNoteNumber = virtualKeyboard->GetKey() + virtualKeyboardMinimumNoteNumber;

  if (lastVirtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber
    && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) {
    IMidiMsg midiMessage;
    midiMessage.MakeNoteOffMsg(lastVirtualKeyboardNoteNumber, 0);
    mMIDIReceiver.onMessageReceived(&midiMessage);
  }

  if (virtualKeyboardNoteNumber >= virtualKeyboardMinimumNoteNumber
    && virtualKeyboardNoteNumber != lastVirtualKeyboardNoteNumber) {
    IMidiMsg midiMessage;
    midiMessage.MakeNoteOnMsg(virtualKeyboardNoteNumber, virtualKeyboard->GetVelocity(), 0);
    mMIDIReceiver.onMessageReceived(&midiMessage);
  }

  lastVirtualKeyboardNoteNumber = virtualKeyboardNoteNumber;
}
Exemple #7
0
void MIDIReceiver::advance() {
	while (!mMidiQueue.Empty()) {
		IMidiMsg* midiMessage = mMidiQueue.Peek();
		if (midiMessage->mOffset > mOffset) break;

		IMidiMsg::EStatusMsg status = midiMessage->StatusMsg();
		int noteNumber = midiMessage->NoteNumber();
		int velocity = midiMessage->Velocity();
		// There are only note on/off messages in the queue, see ::OnMessageReceived
		if (status == IMidiMsg::kNoteOn && velocity) {
			if (mKeyStatus[noteNumber] == false) {
				mKeyStatus[noteNumber] = true;
				mNumKeys += 1;
			}
			// A key pressed later overrides any previously pressed key:
			if (noteNumber != mLastNoteNumber) {
				mLastNoteNumber = noteNumber;
				mLastFrequency = noteNumberToFrequency(mLastNoteNumber);
				mLastVelocity = velocity;
			}
		}
		else {
			if (mKeyStatus[noteNumber] == true) {
				mKeyStatus[noteNumber] = false;
				mNumKeys -= 1;
			}
			// If the last note was released, nothing should play:
			if (noteNumber == mLastNoteNumber) {
				mLastNoteNumber = -1;
				mLastFrequency = -1;
				mLastVelocity = 0;
			}
		}
		mMidiQueue.Remove();
	}
	mOffset++;
}
tresult PLUGIN_API IPlugVST3Plugin::process(ProcessData& data)
{
  TRACE_PROCESS;

  IMutexLock lock(this);

  if(data.processContext)
    memcpy(&mProcessContext, data.processContext, sizeof(ProcessContext));

  //process parameters
  IParameterChanges* paramChanges = data.inputParameterChanges;
  if (paramChanges)
  {
    int32 numParamsChanged = paramChanges->getParameterCount();

    //it is possible to get a finer resolution of control here by retrieving more values (points) from the queue
    //for now we just grab the last one

    for (int32 i = 0; i < numParamsChanged; i++)
    {
      IParamValueQueue* paramQueue = paramChanges->getParameterData(i);
      if (paramQueue)
      {
        int32 numPoints = paramQueue->getPointCount();
        int32 offsetSamples;
        double value;

        if (paramQueue->getPoint(numPoints - 1,  offsetSamples, value) == kResultTrue)
        {
          int idx = paramQueue->getParameterId();

          switch (idx)
          {
            case kBypassParam:
            {
              bool bypassed = (value > 0.5);
              
              if (bypassed != mIsBypassed)
              {
                mIsBypassed = bypassed;
              }

              break;
            }
            case kPresetParam:
              RestorePreset(FromNormalizedParam(value, 0, NPresets(), 1.));
              break;
              //TODO pitch bend, modwheel etc
            default:
              if (idx >= 0 && idx < NParams())
              {
                GetParam(idx)->SetNormalized((double)value);
                if (GetGUI()) GetGUI()->SetParameterFromPlug(idx, (double)value, true);
                OnParamChange(idx);
              }
              break;
          }

        }
      }
    }
  }

  if(DoesMIDI())
  {
    //process events.. only midi note on and note off?
    IEventList* eventList = data.inputEvents;
    if (eventList)
    {
      int32 numEvent = eventList->getEventCount();
      for (int32 i=0; i<numEvent; i++)
      {
        Event event;
        if (eventList->getEvent(i, event) == kResultOk)
        {
          IMidiMsg msg;
          switch (event.type)
          {
            case Event::kNoteOnEvent:
            {
              msg.MakeNoteOnMsg(event.noteOn.pitch, event.noteOn.velocity * 127, event.sampleOffset, event.noteOn.channel);
              ProcessMidiMsg(&msg);
              break;
            }

            case Event::kNoteOffEvent:
            {
              msg.MakeNoteOffMsg(event.noteOff.pitch, event.sampleOffset, event.noteOff.channel);
              ProcessMidiMsg(&msg);
              break;
            }
          }
        }
      }
    }
  }

#pragma mark process single precision

  if (processSetup.symbolicSampleSize == kSample32)
  {
    if (data.numInputs)
    {
      if (mScChans)
      {
        if (getAudioInput(1)->isActive()) // Sidechain is active
        {
          mSidechainActive = true;
          SetInputChannelConnections(0, NInChannels(), true);
        }
        else
        {
          if (mSidechainActive)
          {
            ZeroScratchBuffers();
            mSidechainActive = false;
          }

          SetInputChannelConnections(0, NInChannels(), true);
          SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - mScChans, false);
        }

        AttachInputBuffers(0, NInChannels() - mScChans, data.inputs[0].channelBuffers32, data.numSamples);
        AttachInputBuffers(mScChans, NInChannels() - mScChans, data.inputs[1].channelBuffers32, data.numSamples);
      }
      else
      {
        SetInputChannelConnections(0, data.inputs[0].numChannels, true);
        SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - data.inputs[0].numChannels, false);
        AttachInputBuffers(0, NInChannels(), data.inputs[0].channelBuffers32, data.numSamples);
      }
    }

    for (int outBus = 0, chanOffset = 0; outBus < data.numOutputs; outBus++)
    {
      int busChannels = data.outputs[outBus].numChannels;
      SetOutputChannelConnections(chanOffset, busChannels, (bool) getAudioOutput(outBus)->isActive());
      SetOutputChannelConnections(chanOffset + busChannels, NOutChannels() - (chanOffset + busChannels), false);
      AttachOutputBuffers(chanOffset, busChannels, data.outputs[outBus].channelBuffers32);
      chanOffset += busChannels;
    }

    if (mIsBypassed)
      PassThroughBuffers(0.0f, data.numSamples);
    else
      ProcessBuffers(0.0f, data.numSamples); // process buffers single precision
  }

#pragma mark process double precision

  else if (processSetup.symbolicSampleSize == kSample64)
  {
    if (data.numInputs)
    {
      if (mScChans)
      {
        if (getAudioInput(1)->isActive()) // Sidechain is active
        {
          mSidechainActive = true;
          SetInputChannelConnections(0, NInChannels(), true);
        }
        else
        {
          if (mSidechainActive)
          {
            ZeroScratchBuffers();
            mSidechainActive = false;
          }

          SetInputChannelConnections(0, NInChannels(), true);
          SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - mScChans, false);
        }

        AttachInputBuffers(0, NInChannels() - mScChans, data.inputs[0].channelBuffers64, data.numSamples);
        AttachInputBuffers(mScChans, NInChannels() - mScChans, data.inputs[1].channelBuffers64, data.numSamples);
      }
      else
      {
        SetInputChannelConnections(0, data.inputs[0].numChannels, true);
        SetInputChannelConnections(data.inputs[0].numChannels, NInChannels() - data.inputs[0].numChannels, false);
        AttachInputBuffers(0, NInChannels(), data.inputs[0].channelBuffers64, data.numSamples);
      }
    }

    for (int outBus = 0, chanOffset = 0; outBus < data.numOutputs; outBus++)
    {
      int busChannels = data.outputs[outBus].numChannels;
      SetOutputChannelConnections(chanOffset, busChannels, (bool) getAudioOutput(outBus)->isActive());
      SetOutputChannelConnections(chanOffset + busChannels, NOutChannels() - (chanOffset + busChannels), false);
      AttachOutputBuffers(chanOffset, busChannels, data.outputs[outBus].channelBuffers64);
      chanOffset += busChannels;
    }

    if (mIsBypassed)
      PassThroughBuffers(0.0, data.numSamples);
    else
      ProcessBuffers(0.0, data.numSamples); // process buffers double precision
  }

// Midi Out
//  if (mDoesMidi) {
//    IEventList eventList = data.outputEvents;
//
//    if (eventList)
//    {
//      Event event;
//
//      while (!mMidiOutputQueue.Empty()) {
//        //TODO: parse events and add
//        eventList.addEvent(event);
//      }
//    }
//  }

  return kResultOk;
}
void IPlugInstrument::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
	double* output = outputs[0];
	for (int offset = 0; offset < nFrames; ++offset)
	{

		// Handle any MIDI messages in the queue.
		while (!mMidiQueue.Empty())
		{
			IMidiMsg* pMsg = mMidiQueue.Peek();
			// Stop when we've reached the current sample frame (offset).
			if (pMsg->mOffset > offset)
				break;

			// Handle the MIDI message.
			int status = pMsg->StatusMsg();
			switch (status)
			{
				case IMidiMsg::kNoteOn:
				case IMidiMsg::kNoteOff:
				{
					int velocity = pMsg->Velocity();
					// Note On
					if (status == IMidiMsg::kNoteOn && velocity)
					{
						mNote = pMsg->NoteNumber();
						mFreq = 440. * pow(2., (mNote - 69.) / 12.);
						mGain = velocity / 127.;
					}
					// Note Off
					else // if (status == IMidiMsg::kNoteOff || !velocity)
					{
						if (pMsg->NoteNumber() == mNote)
							mNote = NONE;
					}
					break;
				}

				case IMidiMsg::kControlChange:
					switch (pMsg->ControlChangeIdx())
					{
						case IMidiMsg::kChannelVolume:
							mVolume = pMsg->ControlChange(IMidiMsg::kChannelVolume);
							break;

						case IMidiMsg::kAllNotesOff:
							if (mNote != NONE || mPhase != 0.)
							{
								mNote = NONE;
								mPhase = 0.;
							}
							break;
					}
					break;
			}

			// Delete the MIDI message we've just handled from the queue.
			mMidiQueue.Remove();
		}

		// Now that the MIDI messages have been handled we are ready to
		// generate a sample of audio.
		if (mNote == NONE)
		{
			*output++ = 0.;
		}
		else // if (mNote != NONE)
		{
			double gain = mVolume;
			if (mVelocity)
				gain *= mGain;

			// Output a (non-band-limited) square wave.
			double phase = mPhase * mFreq;
			if (phase - floor(phase) < 0.50) // 50% duty cycle
				*output++ = +gain;
			else
				*output++ = -gain;
		}

		mPhase += mSamplePeriod;
	}

	// Try to keep the phase below 1.
	if (mNote == NONE && mPhase >= 1.)
		mPhase -= floor(mPhase);

	// Update the offsets of any MIDI messages still in the queue.
	mMidiQueue.Flush(nFrames);
}
Exemple #10
0
 bool operator() (IMidiMsg& a, IMidiMsg& b) { return (a.NoteNumber() < b.NoteNumber()); }
Exemple #11
0
void Sequence::rebuild()
{
    int held = keymap_.held();

    playLength_ = held * octaves_;
    if (arpMode_ == kUpDown && (held*octaves_ > 2)) {
        playLength_ += playLength_ - 2;
    }

    if (insertMode_ == kInsertLow || insertMode_ == kInsertHi) {
        playLength_ *= 2;
    }

    if (playLength_ > length()) {
        sequence.resize(playLength_);
    }

    //  clear all notes, reset position if none held
    if (held == 0) {
        for (int i=0; i < length(); ++i) {
            get(i)->MakeNoteOffMsg(0, 0);        
        }
        pos = 0;
    }
    else {
        std::vector<IMidiMsg> input = keymap_.sortedEvents();

        IMidiMsg loNote = input.front();
        IMidiMsg hiNote = input.back();
        hiNote.MakeNoteOnMsg(hiNote.NoteNumber() + 12*(octaves_-1), hiNote.Velocity(), hiNote.mOffset);

        if (arpMode_ == kUp || arpMode_ == kDown || arpMode_ == kUpDown) {
            if (arpMode_ == kDown) {
                std::reverse(input.begin(), input.end());
            }
        }
        else {
            //  default others to manual for now
            input = keymap_.events;
        }

        int iLast;
        for (int oct=0; oct < octaves_; ++oct) {
            int noteOffset = (arpMode_ == kDown) ? ((octaves_-1)*12 - oct*12) : oct*12;

            for (int i=0; i < held; ++i) {
                IMidiMsg* inp = &(input[i % held]);
                iLast = i + oct*held;
                get(iLast)->MakeNoteOnMsg(inp->NoteNumber() + noteOffset, inp->Velocity(), inp->mOffset);
            }
        }

        //  Mirror the ascending sequence to produce an up/down sequence
        int iNext = iLast+1;
        if (arpMode_ == kUpDown) {
            while (--iLast > 0) {
                IMidiMsg* lastMsg = get(iLast);
                get(iNext++)->MakeNoteOnMsg(lastMsg->NoteNumber(), lastMsg->Velocity(), lastMsg->mOffset);
            }
        }

        if (insertMode_ == kInsertLow || insertMode_ == kInsertHi) {
            IMidiMsg& insertNote = (insertMode_ == kInsertLow) ? loNote : hiNote;
            // XXX change to using a member buffer instead of instantiating every time
            std::vector<IMidiMsg> seqcopy = sequence;
            int idx = 0;
            std::vector<IMidiMsg>::iterator prev = seqcopy.begin() + (playLength_/2 - 1);
            for (std::vector<IMidiMsg>::iterator it = seqcopy.begin(); 
              it != seqcopy.begin() + (playLength_/2); ++it) {
                  if (it->NoteNumber() != insertNote.NoteNumber() && prev->NoteNumber() != insertNote.NoteNumber()) {
                    sequence[idx++] = insertNote;
                  }
                  sequence[idx++] = *it;
                  prev = it;
            }
            playLength_ = idx;
        }
    }
}
Exemple #12
0
Sequence::Sequence(KeyMap& keymap, int length) : keymap_(keymap), pos(0), playLength_(0), octaves_(1), arpMode_(kUp), insertMode_(kInsertOff)
{
    IMidiMsg off;
    off.MakeNoteOffMsg(0, 0);
    sequence.insert(sequence.begin(), length, off);
}
Exemple #13
0
tresult PLUGIN_API IPlugVST3::process(ProcessData& data)
{ 
  TRACE_PROCESS;
  
  IMutexLock lock(this); // TODO: is this the best place to lock the mutex?
  
  memcpy(&mProcessContext, data.processContext, sizeof(ProcessContext));
  
  //process parameters
  IParameterChanges* paramChanges = data.inputParameterChanges;
  if (paramChanges)
  {
    int32 numParamsChanged = paramChanges->getParameterCount();
    
    //it is possible to get a finer resolution of control here by retrieving more values (points) from the queue
    //for now we just grab the last one
    
    for (int32 i = 0; i < numParamsChanged; i++)
    {
      IParamValueQueue* paramQueue = paramChanges->getParameterData(i);
      if (paramQueue)
      {
        int32 numPoints = paramQueue->getPointCount();
        int32 offsetSamples;
        double value;
        
        if (paramQueue->getPoint(numPoints - 1,  offsetSamples, value) == kResultTrue)
        {
          int idx = paramQueue->getParameterId();
          if (idx >= 0 && idx < NParams()) 
          {
            GetParam(idx)->SetNormalized((double)value);
            if (GetGUI()) GetGUI()->SetParameterFromPlug(idx, (double)value, true);
            OnParamChange(idx);
          }
        }
      }
    }
  }
  
  if(mDoesMidi) {
    //process events.. only midi note on and note off?
    IEventList* eventList = data.inputEvents;
    if (eventList) 
    {
      int32 numEvent = eventList->getEventCount();
      for (int32 i=0; i<numEvent; i++)
      {
        Event event;
        if (eventList->getEvent(i, event) == kResultOk)
        {
          IMidiMsg msg;
          switch (event.type)
          {
            case Event::kNoteOnEvent:
            {
              msg.MakeNoteOnMsg(event.noteOn.pitch, event.noteOn.velocity * 127, event.sampleOffset, event.noteOn.channel);
              ProcessMidiMsg(&msg);
              break;
            }
              
            case Event::kNoteOffEvent:
            {
              msg.MakeNoteOffMsg(event.noteOff.pitch, event.sampleOffset, event.noteOff.channel);
              ProcessMidiMsg(&msg);
              break;
            }
          }
        }
      }
    }
  }
  
  //process audio
  if (data.numInputs == 0 || data.numOutputs == 0)
  {
    // nothing to do
    return kResultOk;
  }
  
  if (processSetup.symbolicSampleSize == kSample32)
  {
    float** in  = data.inputs[0].channelBuffers32;
    float** out = data.outputs[0].channelBuffers32;
    
    if (mScChans) 
    {
      float** side = data.inputs[1].channelBuffers32;

      if (getAudioInput(1)->isActive()) 
      {
        int totalNInputs = data.inputs[0].numChannels + data.inputs[1].numChannels;
        
        float** allInputs = new float*[totalNInputs];

        for (int i = 0; i < data.inputs[0].numChannels; i ++) {
          allInputs[i] = in[i];
        }
        
        for (int i = 0; i < data.inputs[1].numChannels; i ++) {
          allInputs[i + data.inputs[0].numChannels] = side[i];
        }
        
        AttachInputBuffers(0, totalNInputs, allInputs, data.numSamples);
        mSideChainIsConnected = true;
        
        delete [] allInputs;
      }
      else 
      {
        AttachInputBuffers(0, data.inputs[0].numChannels, in, data.numSamples);
        mSideChainIsConnected = false;
      }
    }
    else 
    {
      AttachInputBuffers(0, data.inputs[0].numChannels, in, data.numSamples);
    }
    
    AttachOutputBuffers(0, data.outputs[0].numChannels, out);
    ProcessBuffers(0.0f, data.numSamples);
  }
  else if (processSetup.symbolicSampleSize == kSample64) // TODO: parity for double precision
  {
    double** in  = data.inputs[0].channelBuffers64;
    double** out = data.outputs[0].channelBuffers64;
    
    AttachInputBuffers(0, data.inputs[0].numChannels, in, data.numSamples);
    AttachOutputBuffers(0, data.outputs[0].numChannels, out);
    
    ProcessBuffers(0.0, data.numSamples);
  } 
  
  // Midi Out
//  if (mDoesMidi) {
//    IEventList eventList = data.outputEvents;
//    
//    if (eventList) 
//    {
//      Event event;
//      
//      while (!mMidiOutputQueue.Empty()) {
//        //TODO: parse events and add
//        eventList.addEvent(event);
//      }
//    }
//  }
  
  return kResultOk; 
}
Exemple #14
0
void IPlugMultiTargets::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
  // Mutex is already locked for us.
  double* in1 = inputs[0];
  double* in2 = inputs[1];
  double* out1 = outputs[0];
  double* out2 = outputs[1];
  double peakL = 0.0, peakR = 0.0;
  
  GetTime(&mTimeInfo);
  
  IKeyboardControl* pKeyboard = (IKeyboardControl*) mKeyboard;
  
  if (pKeyboard->GetKey() != mKey)
  {
    IMidiMsg msg;
    
    if (mKey >= 0) {
      msg.MakeNoteOffMsg(mKey + 48, 0, 0);
      mMidiQueue.Add(&msg);
    }
    
    mKey = pKeyboard->GetKey();
    
    if (mKey >= 0) {
      msg.MakeNoteOnMsg(mKey + 48, pKeyboard->GetVelocity(), 0, 0);
      mMidiQueue.Add(&msg);
    }
  }
  
  for (int offset = 0; offset < nFrames; ++offset, ++in1, ++in2, ++out1, ++out2)
  {
    while (!mMidiQueue.Empty())
    {
      IMidiMsg* pMsg = mMidiQueue.Peek();
      if (pMsg->mOffset > offset) break;
      
      // TODO: make this work on win sa
      #if !defined(OS_WIN) && !defined(SA_API)
        SendMidiMsg(pMsg);
      #endif
      
      int status = pMsg->StatusMsg();
      
      switch (status)
      {
        case IMidiMsg::kNoteOn:
        case IMidiMsg::kNoteOff:
        {
          int velocity = pMsg->Velocity();
          // Note On
          if (status == IMidiMsg::kNoteOn && velocity)
          {
            mNote = pMsg->NoteNumber();
            mFreq = 440. * pow(2., (mNote - 69.) / 12.);
            mNoteGain = velocity / 127.;
          }
          // Note Off
          else // if (status == IMidiMsg::kNoteOff || !velocity)
          {
            if (pMsg->NoteNumber() == mNote)
              mNote = -1;
            
            mNoteGain = 0.;
          }
          break;
        }
      }
      
      mMidiQueue.Remove();
    }
    
    *out1 = sin( 2. * M_PI * mFreq * mPhase / mSampleRate ) * mGainLSmoother.Process(mGainL * mNoteGain);
    *out2 = sin( 2. * M_PI * mFreq * 1.01 * (mPhase++) / mSampleRate ) * mGainRSmoother.Process(mGainR * mNoteGain);
    
  	peakL = IPMAX(peakL, fabs(*out1));
		peakR = IPMAX(peakR, fabs(*out2));
	}
  
	const double METER_ATTACK = 0.6, METER_DECAY = 0.05;
	double xL = (peakL < mPrevL ? METER_DECAY : METER_ATTACK);
	double xR = (peakR < mPrevR ? METER_DECAY : METER_ATTACK);
  
	peakL = peakL * xL + mPrevL * (1.0 - xL);
	peakR = peakR * xR + mPrevR * (1.0 - xR);
  
	mPrevL = peakL;
	mPrevR = peakR;
  
  if (GetGUI())
  {
    GetGUI()->SetControlFromPlug(mMeterIdx_L, peakL);
    GetGUI()->SetControlFromPlug(mMeterIdx_R, peakR);
  }
  
  mMidiQueue.Flush(nFrames);
}