Exemple #1
0
bool MidiDevice::sendNullRPNParams(unsigned time, int port, int chn, bool nrpn)
{
  if(_port == -1)
    return false;  
    
  int nv = MusEGlobal::midiPorts[_port].nullSendValue();
  if(nv == -1)
    return false;  
  
  int nvh = (nv >> 8) & 0xff;
  int nvl = nv & 0xff;
  if(nvh != 0xff)
  {
    if(nrpn)
      putMidiEvent(MidiPlayEvent(time, port, chn, ME_CONTROLLER, CTRL_HNRPN, nvh & 0x7f));
    else
      putMidiEvent(MidiPlayEvent(time, port, chn, ME_CONTROLLER, CTRL_HRPN, nvh & 0x7f));
  }
  if(nvl != 0xff)
  {
    if(nrpn)
      putMidiEvent(MidiPlayEvent(time, port, chn, ME_CONTROLLER, CTRL_LNRPN, nvl & 0x7f));
    else  
      putMidiEvent(MidiPlayEvent(time, port, chn, ME_CONTROLLER, CTRL_LRPN, nvl & 0x7f));
  }
  return true;  
}
Exemple #2
0
void Audio::panic()
{
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		MidiPort* port = &midiPorts[i];
		if (port == 0) // ??
			continue;
		for (int chan = 0; chan < MIDI_CHANNELS; ++chan)
		{
			if (debugMsg)
				 printf("send all sound of to midi port %d channel %d\n", i, chan);
			port->sendEvent(MidiPlayEvent(0, i, chan, ME_CONTROLLER, CTRL_ALL_SOUNDS_OFF, 0), true);
			port->sendEvent(MidiPlayEvent(0, i, chan, ME_CONTROLLER, CTRL_RESET_ALL_CTRL, 0), true);
		}
	}
}
Exemple #3
0
bool MidiJackDevice::processEvent(const MidiPlayEvent& event)
{
    int chn = event.channel();
    unsigned t = event.time();
    int a = event.dataA();
    int b = event.dataB();
    // Perhaps we can find use for this value later, together with the Jack midi LOS port(s).
    // No big deal if not. Not used for now.
    int port = event.port();

    // TODO: No sub-tick playback resolution yet, with external sync.
    // Just do this 'standard midi 64T timing thing' for now until we figure out more precise external timings.
    // Does require relatively short audio buffers, in order to catch the resolution, but buffer <= 256 should be OK...
    // Tested OK so far with 128.
    if (t == 0 /*|| extSyncFlag.value()*/)
        t = audio->getFrameOffset() + audio->pos().frame();

#ifdef JACK_MIDI_DEBUG
    //printf("MidiJackDevice::processEvent time:%d type:%d ch:%d A:%d B:%d\n", event.time(), event.type(), event.channel(), event.dataA(), event.dataB());
#endif

    //Send to monitor thread for processing
    monitorOutputEvent(event);

    if (event.type() == ME_PROGRAM)
    {
        // don't output program changes for GM drum channel
        int hb = (a >> 16) & 0xff;
        int lb = (a >> 8) & 0xff;
        int pr = a & 0x7f;

        //TODO: NOTE this is where program changes are sent we can later debug this to diagnose the dropped events
        if (hb != 0xff)
        {
            if(!queueEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HBANK, hb)))
                return false;
        }
        if (lb != 0xff)
        {
            if(!queueEvent(MidiPlayEvent(t + 1, port, chn, ME_CONTROLLER, CTRL_LBANK, lb)))
                return false;
        }
        //sleep(1);
        if(!queueEvent(MidiPlayEvent(t + 2, port, chn, ME_PROGRAM, pr, 0)))
            return false;
    }
Exemple #4
0
void Audio::sendLocalOff()
{
	for (int k = 0; k < MIDI_PORTS; ++k)
	{
		for (int i = 0; i < MIDI_CHANNELS; ++i)
			midiPorts[k].sendEvent(MidiPlayEvent(0, k, i, ME_CONTROLLER, CTRL_LOCAL_OFF, 0));
	}
}
Exemple #5
0
bool MidiDevice::putEvent(const MidiPlayEvent& ev)
      {
      if(!_writeEnable)
        //return true;
        return false;
        
      unsigned t = ev.time();
      int port = ev.port();
      
      if (ev.type() == ME_CONTROLLER) {
            int a = ev.dataA();
            int b = ev.dataB();
            int chn = ev.channel();
            if (a == CTRL_PITCH) {
                  return putMidiEvent(MidiPlayEvent(t, port, chn, ME_PITCHBEND, b, 0));
                  }
            if ((a | 0xff) == CTRL_POLYAFTER) {
                  return putMidiEvent(MidiPlayEvent(t, port, chn, ME_POLYAFTER, a & 0x7f, b & 0x7f));
                  }
            if (a == CTRL_AFTERTOUCH) {
                  return putMidiEvent(MidiPlayEvent(t, port, chn, ME_AFTERTOUCH, b, 0));
                  }
            if (a == CTRL_PROGRAM) {
                        int hb = (b >> 16) & 0xff;
                        int lb = (b >> 8) & 0xff;
                        int pr = b & 0x7f;
                        if (hb != 0xff)
                              putMidiEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_HBANK, hb));
                        if (lb != 0xff)
                              putMidiEvent(MidiPlayEvent(t, port, chn, ME_CONTROLLER, CTRL_LBANK, lb));
                        return putMidiEvent(MidiPlayEvent(t, port, chn, ME_PROGRAM, pr, 0));
                  }
Exemple #6
0
void MidiJackDevice::recordEvent(MidiRecordEvent& event)/*{{{*/
{
    if (audio->isPlaying())
        event.setLoopNum(audio->loopCount());

    if (midiInputTrace)
    {
        printf("Jack MidiInput: ");
        event.dump();
    }

    int typ = event.type();

    if (_port != -1)
    {
        //call our midimonitor with the data, it can then decide what to do
        monitorEvent(event);
    }

    //
    //  process midi event input filtering and
    //    transformation
    //

    processMidiInputTransformPlugins(event);

    if (filterEvent(event, midiRecordType, false))
        return;

    if (!applyMidiInputTransformation(event))
    {
        if (midiInputTrace)
            printf("   midi input transformation: event filtered\n");
        return;
    }

    //
    // transfer noteOn events to gui for step recording and keyboard
    // remote control
    //
    if (typ == ME_NOTEON)
    {
        int pv = ((event.dataA() & 0xff) << 8) + (event.dataB() & 0xff);
        song->putEvent(pv);
    }
    //This was not sending noteoff events at all sometimes causing strange endless note in step rec
    else if(typ == ME_NOTEOFF)
    {
        int pv = ((event.dataA() & 0xff) << 8) + (0x00);
        song->putEvent(pv);
    }

    // Do not bother recording if it is NOT actually being used by a port.
    // Because from this point on, process handles things, by selected port.
    if (_port == -1)
        return;

    // Split the events up into channel fifos. Special 'channel' number 17 for sysex events.
    unsigned int ch = (typ == ME_SYSEX) ? kMaxMidiChannels : event.channel();
    if (_recordFifo[ch].put(MidiPlayEvent(event)))
        printf("MidiJackDevice::recordEvent: fifo channel %d overflow\n", ch);
}/*}}}*/
Exemple #7
0
 if (a < CTRL_14_OFFSET) {          // 7 Bit Controller
     l->add(MidiPlayEvent(tick, port, channel, ME_CONTROLLER, a, b));
 }
 else if (a < CTRL_RPN_OFFSET) {     // 14 Bit Controller
     int ctrlH = (a >> 8) & 0x7f;
     int ctrlL = a & 0x7f;
     int dataH = (b >> 7) & 0x7f;
     int dataL = b & 0x7f;
     l->add(MidiPlayEvent(tick, port, channel, ME_CONTROLLER, ctrlH, dataH));
     l->add(MidiPlayEvent(tick+1, port, channel, ME_CONTROLLER, ctrlL, dataL));
 }
 else if (a < CTRL_NRPN_OFFSET) {     // RPN 7-Bit Controller
     int ctrlH = (a >> 8) & 0x7f;
     int ctrlL = a & 0x7f;
     l->add(MidiPlayEvent(tick, port, channel, ME_CONTROLLER, CTRL_HRPN, ctrlH));
     l->add(MidiPlayEvent(tick+1, port, channel, ME_CONTROLLER, CTRL_LRPN, ctrlL));
     l->add(MidiPlayEvent(tick+2, port, channel, ME_CONTROLLER, CTRL_HDATA, b));
 }
 else if (a < CTRL_INTERNAL_OFFSET) {     // NRPN 7-Bit Controller
     int ctrlH = (a >> 8) & 0x7f;
     int ctrlL = a & 0x7f;
     l->add(MidiPlayEvent(tick, port, channel, ME_CONTROLLER, CTRL_HNRPN, ctrlH));
     l->add(MidiPlayEvent(tick+1, port, channel, ME_CONTROLLER, CTRL_LNRPN, ctrlL));
     l->add(MidiPlayEvent(tick+2, port, channel, ME_CONTROLLER, CTRL_HDATA, b));
 }
 else if (a == CTRL_PITCH) {
     int a = b + 8192;
     int b = a >> 7;
     l->add(MidiPlayEvent(tick, port, channel, ME_PITCHBEND, a & 0x7f, b & 0x7f));
 }
 else if (a == CTRL_PROGRAM) {
Exemple #8
0
 virtual MidiPlayEvent receiveEvent() { return MidiPlayEvent(); }
Exemple #9
0
void MidiDevice::handleSeek()
{
  // If the device is not in use by a port, don't bother it.
  if(_port == -1)
    return;
  
  MidiPort* mp = &MusEGlobal::midiPorts[_port];
  MidiInstrument* instr = mp->instrument();
  MidiCtrlValListList* cll = mp->controller();
  unsigned pos = MusEGlobal::audio->tickPos();
  
  //---------------------------------------------------
  //    Send STOP 
  //---------------------------------------------------
    
  // Don't send if external sync is on. The master, and our sync routing system will take care of that.  
  if(!MusEGlobal::extSyncFlag.value())
  {
    if(mp->syncInfo().MRTOut())
    {
      // Shall we check for device write open flag to see if it's ok to send?...
      //if(!(rwFlags() & 0x1) || !(openFlags() & 1))
      //if(!(openFlags() & 1))
      //  continue;
      mp->sendStop();
    }    
  }

  //---------------------------------------------------
  //    If playing, clear all notes and flush out any
  //     stuck notes which were put directly to the device
  //---------------------------------------------------
  
  if(MusEGlobal::audio->isPlaying()) 
  {
    _playEvents.clear();
    for(iMPEvent i = _stuckNotes.begin(); i != _stuckNotes.end(); ++i) 
    {
      MidiPlayEvent ev(*i);
      ev.setTime(0);
      putEvent(ev);  // For immediate playback try putEvent, putMidiEvent, or sendEvent (for the optimizations).
    }
    _stuckNotes.clear();
  }
  
  //---------------------------------------------------
  //    Send new controller values
  //---------------------------------------------------
    
  // Find channels on this port used in the song...
  bool usedChans[MIDI_CHANNELS];
  int usedChanCount = 0;
  for(int i = 0; i < MIDI_CHANNELS; ++i)
    usedChans[i] = false;
  if(MusEGlobal::song->click() && MusEGlobal::clickPort == _port)
  {
    usedChans[MusEGlobal::clickChan] = true;
    ++usedChanCount;
  }
  bool drum_found = false;
  for(ciMidiTrack imt = MusEGlobal::song->midis()->begin(); imt != MusEGlobal::song->midis()->end(); ++imt)
  {
    //------------------------------------------------------------
    //    While we are at it, flush out any track-related playback stuck notes
    //     (NOT 'live' notes) which were not put directly to the device
    //------------------------------------------------------------
    MPEventList& mel = (*imt)->stuckNotes;
    for(iMPEvent i = mel.begin(), i_next = i; i != mel.end(); i = i_next)
    {
      ++i_next;

      if((*i).port() != _port)
        continue;
      MidiPlayEvent ev(*i);
      ev.setTime(0);
      putEvent(ev); // For immediate playback try putEvent, putMidiEvent, or sendEvent (for the optimizations).
      mel.erase(i);
    }
    
    if((*imt)->type() == MusECore::Track::DRUM)
    {
      if(!drum_found)
      {
        drum_found = true; 
        for(int i = 0; i < DRUM_MAPSIZE; ++i)
        {
          // Default to track port if -1 and track channel if -1.
          int mport = MusEGlobal::drumMap[i].port;
          if(mport == -1)
            mport = (*imt)->outPort();
          int mchan = MusEGlobal::drumMap[i].channel;
          if(mchan == -1)
            mchan = (*imt)->outChannel();
          if(mport != _port || usedChans[mchan])
            continue;
          usedChans[mchan] = true;
          ++usedChanCount;
          if(usedChanCount >= MIDI_CHANNELS)
            break;  // All are used, done searching.
        }
      }
    }
    else
    {
      if((*imt)->outPort() != _port || usedChans[(*imt)->outChannel()])
        continue;
      usedChans[(*imt)->outChannel()] = true;
      ++usedChanCount;
    }

    if(usedChanCount >= MIDI_CHANNELS)
      break;    // All are used. Done searching.
  }   
  
  for(iMidiCtrlValList ivl = cll->begin(); ivl != cll->end(); ++ivl) 
  {
    MidiCtrlValList* vl = ivl->second;
    int chan = ivl->first >> 24;
    if(!usedChans[chan])  // Channel not used in song?
      continue;
    int ctlnum = vl->num();

    // Find the first non-muted value at the given tick...
    bool values_found = false;
    bool found_value = false;
    
    iMidiCtrlVal imcv = vl->lower_bound(pos);
    if(imcv != vl->end() && imcv->first == (int)pos)
    {
      for( ; imcv != vl->end() && imcv->first == (int)pos; ++imcv)
      {
        const Part* p = imcv->second.part;
        if(!p)
          continue;
        // Ignore values that are outside of the part.
        if(pos < p->tick() || pos >= (p->tick() + p->lenTick()))
          continue;
        values_found = true;
        // Ignore if part or track is muted or off.
        if(p->mute())
          continue;
        const Track* track = p->track();
        if(track && (track->isMute() || track->off()))
          continue;
        found_value = true;
        break;
      }
    }
    else
    {
      while(imcv != vl->begin())
      {
        --imcv;
        const Part* p = imcv->second.part;
        if(!p)
          continue;
        // Ignore values that are outside of the part.
        unsigned t = imcv->first;
        if(t < p->tick() || t >= (p->tick() + p->lenTick()))
          continue;
        values_found = true;
        // Ignore if part or track is muted or off.
        if(p->mute())
          continue;
        const Track* track = p->track();
        if(track && (track->isMute() || track->off()))
          continue;
        found_value = true;
        break;
      }
    }

    if(found_value)
    {
      // Don't bother sending any sustain values if not playing. Just set the hw state.
      if(ctlnum == CTRL_SUSTAIN && !MusEGlobal::audio->isPlaying())
        mp->setHwCtrlState(chan, CTRL_SUSTAIN, imcv->second.val);
      else
        // Use sendEvent to get the optimizations and limiting. But force if there's a value at this exact position.
        // NOTE: Why again was this forced? There was a reason. Think it was RJ in response to bug rep, then I modded.
        // A reason not to force: If a straight line is drawn on graph, multiple identical events are stored
        //  (which must be allowed). So seeking through them here sends them all redundantly, not good. // REMOVE Tim.
        mp->sendEvent(MidiPlayEvent(0, _port, chan, ME_CONTROLLER, ctlnum, imcv->second.val), false); //, imcv->first == pos);
        //mp->sendEvent(MidiPlayEvent(0, _port, chan, ME_CONTROLLER, ctlnum, imcv->second.val), pos == 0 || imcv->first == pos);
    }

    // Either no value was found, or they were outside parts, or pos is in the unknown area before the first value.
    // Send instrument default initial values.  NOT for syntis. Use midiState and/or initParams for that. 
    //if((imcv == vl->end() || !done) && !MusEGlobal::song->record() && instr && !isSynti()) 
    // Hmm, without refinement we can only do this at position 0, due to possible 'skipped' values outside parts, above.
    if(!values_found && MusEGlobal::config.midiSendCtlDefaults && !MusEGlobal::song->record() && pos == 0 && instr && !isSynti())
    {
      MidiControllerList* mcl = instr->controller();
      ciMidiController imc = mcl->find(vl->num());
      if(imc != mcl->end())
      {
        MidiController* mc = imc->second;
        if(mc->initVal() != CTRL_VAL_UNKNOWN)
          // Use sendEvent to get the optimizations and limiting. No force sending. Note the addition of bias.
          mp->sendEvent(MidiPlayEvent(0, _port, chan, ME_CONTROLLER, ctlnum, mc->initVal() + mc->bias()), false);
      }
    }
  }
  
  //---------------------------------------------------
  //    reset sustain
  //---------------------------------------------------
  
  for(int ch = 0; ch < MIDI_CHANNELS; ++ch) 
  {
    if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127) 
    {
      const MidiPlayEvent ev(0, _port, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0);
      putEvent(ev);
    }
  }
  
  //---------------------------------------------------
  //    Send STOP and "set song position pointer"
  //---------------------------------------------------
    
  // Don't send if external sync is on. The master, and our sync routing system will take care of that.  
  if(!MusEGlobal::extSyncFlag.value())
  {
    if(mp->syncInfo().MRTOut())
    {
      //mp->sendStop();   // Moved above
      int beat = (pos * 4) / MusEGlobal::config.division;
      mp->sendSongpos(beat);
    }    
  }
}
Exemple #10
0
MidiPlayEvent SynthPluginDevice::receiveEvent()
{
	if(debugMsg)
    	qWarning("SynthPluginDevice::receiveEvent()");
    return MidiPlayEvent() ;//_sif->receiveEvent();
}
Exemple #11
0
void Audio::collectEvents(MidiTrack* track, unsigned int cts, unsigned int nts)
{
	int port = track->outPort();
	int channel = track->outChannel();
	int defaultPort = port;

	MidiDevice* md = midiPorts[port].device();
	MPEventList* playEvents = md->playEvents();
	MPEventList* stuckNotes = md->stuckNotes();

	PartList* pl = track->parts();
	for (iPart p = pl->begin(); p != pl->end(); ++p)
	{
		MidiPart* part = (MidiPart*) (p->second);
		// dont play muted parts
		if (part->mute())
			continue;
		EventList* events = part->events();
		unsigned partTick = part->tick();
		unsigned partLen = part->lenTick();
		int delay = track->delay;

		if (cts > nts)
		{
			printf("processMidi: FATAL: cur > next %d > %d\n",
					cts, nts);
			return;
		}
		unsigned offset = delay + partTick;
		if (offset > nts)
			continue;
		unsigned stick = (offset > cts) ? 0 : cts - offset;
		unsigned etick = nts - offset;
		// By T356. Do not play events which are past the end of this part.
		if (etick > partLen)
			continue;

		iEvent ie = events->lower_bound(stick);
		iEvent iend = events->lower_bound(etick);

		for (; ie != iend; ++ie)
		{
			Event ev = ie->second;
			port = defaultPort; //Reset each loop
			//
			//  dont play any meta events
			//
			if (ev.type() == Meta)
				continue;
			if (track->type() == Track::DRUM)
			{
				int instr = ev.pitch();
				// ignore muted drums
				if (ev.isNote() && drumMap[instr].mute)
					continue;
			}
			unsigned tick = ev.tick() + offset;
			unsigned frame = tempomap.tick2frame(tick) + frameOffset;
			switch (ev.type())
			{
				case Note:
				{
					int len = ev.lenTick();
					int pitch = ev.pitch();
					int velo = ev.velo();
					if (track->type() == Track::DRUM)
					{
						//
						// Map drum-notes to the drum-map values
						//
						int instr = ev.pitch();
						pitch = drumMap[instr].anote;
						port = drumMap[instr].port; //This changes to non-default port
						channel = drumMap[instr].channel;
						velo = int(double(velo) * (double(drumMap[instr].vol) / 100.0));
					}
					else
					{
						//
						// transpose non drum notes
						//
						pitch += (track->transposition + song->globalPitchShift());
					}

					if (pitch > 127)
						pitch = 127;
					if (pitch < 0)
						pitch = 0;
					velo += track->velocity;
					velo = (velo * track->compression) / 100;
					if (velo > 127)
						velo = 127;
					if (velo < 1) // no off event
						velo = 1;
					len = (len * track->len) / 100;
					if (len <= 0) // dont allow zero length
						len = 1;
					int veloOff = ev.veloOff();

					if (port == defaultPort)
					{
						//printf("Adding event normally: frame=%d port=%d channel=%d pitch=%d velo=%d\n",frame, port, channel, pitch, velo);

						// p3.3.25
						// If syncing to external midi sync, we cannot use the tempo map.
						// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
						if (extSyncFlag.value())
							playEvents->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
						else

							playEvents->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));

						stuckNotes->add(MidiPlayEvent(tick + len, port, channel,
								veloOff ? 0x80 : 0x90, pitch, veloOff));
					}
					else
					{ //Handle events to different port than standard.
						MidiDevice* mdAlt = midiPorts[port].device();
						if (mdAlt)
						{

							// p3.3.25
							if (extSyncFlag.value())
								mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel, 0x90, pitch, velo));
							else

								mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel, 0x90, pitch, velo));

							mdAlt->stuckNotes()->add(MidiPlayEvent(tick + len, port, channel,
									veloOff ? 0x80 : 0x90, pitch, veloOff));
						}
					}

					if (velo > track->activity())
						track->setActivity(velo);
				}
					break;

					// Added by T356.
				case Controller:
				{
					//int len   = ev.lenTick();
					//int pitch = ev.pitch();
					if (track->type() == Track::DRUM)
					{
						int ctl = ev.dataA();
						// Is it a drum controller event, according to the track port's instrument?
						MidiController *mc = midiPorts[defaultPort].drumController(ctl);
						if (mc)
						{
							int instr = ctl & 0x7f;
							ctl &= ~0xff;
							int pitch = drumMap[instr].anote & 0x7f;
							port = drumMap[instr].port; //This changes to non-default port
							channel = drumMap[instr].channel;
							MidiDevice* mdAlt = midiPorts[port].device();
							if (mdAlt)
							{
								// p3.3.25
								// If syncing to external midi sync, we cannot use the tempo map.
								// Therefore we cannot get sub-tick resolution. Just use ticks instead of frames.
								if (extSyncFlag.value())
									mdAlt->playEvents()->add(MidiPlayEvent(tick, port, channel,
										ME_CONTROLLER, ctl | pitch, ev.dataB()));
								else

									//playEvents->add(MidiPlayEvent(frame, port, channel, ev));
									mdAlt->playEvents()->add(MidiPlayEvent(frame, port, channel,
										ME_CONTROLLER, ctl | pitch, ev.dataB()));

							}
							break;
						}
					}
					// p3.3.25
					if (extSyncFlag.value())
						playEvents->add(MidiPlayEvent(tick, port, channel, ev));
					else

						playEvents->add(MidiPlayEvent(frame, port, channel, ev));
				}
					break;


				default:
					// p3.3.25
					if (extSyncFlag.value())
						playEvents->add(MidiPlayEvent(tick, port, channel, ev));
					else

						playEvents->add(MidiPlayEvent(frame, port, channel, ev));

					break;
			}
		}
	}
}
Exemple #12
0
void Audio::preloadControllers()/*{{{*/
{
	midiBusy = true;

	MidiTrackList* tracks = song->midis();
	for (iMidiTrack it = tracks->begin(); it != tracks->end(); ++it)
	{
		MidiTrack* track = *it;
		//activePorts[track->outPort()] = true;
		QList<ProcessList*> pcevents;

		int port = track->outPort();
		int channel = track->outChannel();
		int defaultPort = port;

		MidiDevice* md = midiPorts[port].device();
		if (!md)
		{
			continue;
		}
		MPEventList* playEvents = md->playEvents();
		playEvents->erase(playEvents->begin(), playEvents->end());

		PartList* pl = track->parts();
		for (iPart p = pl->begin(); p != pl->end(); ++p)
		{
			MidiPart* part = (MidiPart*) (p->second);
			EventList* events = part->events();
			unsigned partTick = part->tick();
			//unsigned partLen = part->lenTick();
			int delay = track->delay;

			unsigned offset = delay + partTick;

			for (iEvent ie = events->begin(); ie != events->end(); ++ie)
			{
				Event ev = ie->second;
				port = defaultPort;
				unsigned tick = ev.tick() + offset;
				//unsigned frame = tempomap.tick2frame(tick) + frameOffset;
				switch (ev.dataA())
				{
					case CTRL_PROGRAM:
					{
						ProcessList *pl = new ProcessList;
						pl->port = port;
						pl->channel = channel;
						pl->dataB = ev.dataB();
						bool addEvent = true;
						for(int i = 0; i < pcevents.size(); ++i)
						{
							ProcessList* ipl = pcevents.at(i);
							if(ipl->port == pl->port && ipl->channel == pl->channel && ipl->dataB == pl->dataB)
							{
								addEvent = false;
								break;
							}
						}
						if(addEvent)
						{
							printf("Audio::preloadControllers() Loading event @ tick: %d - on channel: %d - on port: %d - dataA: %d - dataB: %d\n",
								tick, channel, port, ev.dataA(), ev.dataB());
							pcevents.append(pl);
							playEvents->add(MidiPlayEvent(tick, port, channel, ev));
						}
					}
						break;
					default:
						break;
				}
			}
		}
		md->setNextPlayEvent(playEvents->begin());
	}
	midiBusy = false;
}/*}}}*/
Exemple #13
0
MidiPlayEvent VstSynthIF::receiveEvent()
      {
      return MidiPlayEvent();
      }