Ejemplo n.º 1
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;
    }
}
Ejemplo n.º 2
0
void IPlugInstrument::ProcessMidiMsg(IMidiMsg* pMsg)
{
	// List all MIDI messages this plugin will handle.
	switch (pMsg->StatusMsg())
	{
		case IMidiMsg::kNoteOn:
		case IMidiMsg::kNoteOff:
			break;

		case IMidiMsg::kControlChange:
			switch (pMsg->ControlChangeIdx())
			{
				case IMidiMsg::kChannelVolume:
				{
					// Update the volume parameter in the UI only.
					double volume = pMsg->ControlChange(IMidiMsg::kChannelVolume);
					if (GetGUI())
						GetGUI()->SetParameterFromPlug(kVolume, volume, false);
					else
						GetParam(kVolume)->Set(volume);
					InformHostOfParamChange(kVolume, volume);
				}
				break;

				case IMidiMsg::kAllNotesOff:
					break;

				// Discard all other Control Change messages.
				default:
					SendMidiMsg(pMsg);
					return;
			}
			break;

		// Discard all other MIDI messages.
		default:
			SendMidiMsg(pMsg);
			return;
	}

	// Don't handle the MIDI message just yet (we'll do that in
	// ProcessDoubleReplacing), but instead add it to the queue.
	mMidiQueue.Add(pMsg);
}
Ejemplo n.º 3
0
bool IPlugVST::SendMidiMsgs(WDL_TypedBuf<IMidiMsg>* pMsgs)
{
  // Todo: bundle and SendVSTEvents.
  bool rc = true;
  int n = pMsgs->GetSize();
  IMidiMsg* pMsg = pMsgs->Get();
  for (int i = 0; i < n; ++i, ++pMsg) {
    rc &= SendMidiMsg(pMsg);
  }
  return rc;
}
Ejemplo n.º 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;
}
Ejemplo n.º 5
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);
}