Example #1
0
/// Обновление
  void UpdateEvent (const char* name, ResourceState state)
  {
    EventMap::iterator iter = event_map.find (name);

    if (iter == event_map.end ())
    {
      EventPtr event = EventPtr (new EventDesc (name, state), false);

      EventList::iterator iter = event_list.insert (event_list.end (), event);

      event_map.insert_pair (name, iter);
    }
    else
    {
      EventPtr event = *iter->second;

      if (state == event->state)
        return;

      if (event->state == ResourceState_Ignore)
      {
        event_list.splice (event_list.end (), event_list, iter->second);

        event->state = state;

        return;
      }

      switch (state)
      {
        case ResourceState_Unloaded:
          event->state = ResourceState_Ignore;
          break;
        case ResourceState_Prefetched:
          if (event->state != ResourceState_Unloaded)
            return;

          event_list.splice (event_list.end (), event_list, iter->second);

          event->state = state;          

          break;
        case ResourceState_Loaded:
          if (event->state == ResourceState_Unloaded) event->state = ResourceState_Ignore;
          else 
          {
            event_list.splice (event_list.end (), event_list, iter->second);

            event->state = state;
          }

          break;
        default:
          break;
      }
    }    
  }
Example #2
0
void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)/*{{{*/
{
        {
            startUndo();

            MidiPart* nPart = new MidiPart(*(MidiPart*) oPart);
            nPart->setLenTick(len);
            // Indicate no undo, and do port controller values but not clone parts.
            audio->msgChangePart(oPart, nPart, false, true, false);

            // cut Events in nPart
            // Changed by T356. Don't delete events if this is a clone part.
            // The other clones might be longer than this one and need these events.
            if (nPart->cevents()->arefCount() <= 1)
            {
                if (oPart->lenTick() > len)
                {
                    EventList* el = nPart->events();
                    iEvent ie = el->lower_bound(len);
                    for (; ie != el->end();)
                    {
                        iEvent i = ie;
                        ++ie;
                        // Indicate no undo, and do port controller values and clone parts.
                        audio->msgDeleteEvent(i->second, nPart, false, true, true);
                    }
                }
            }

            /*
            // cut Events in nPart
            // Changed by T356. Don't delete events if this is a clone part.
            // The other clones might be longer than this one and need these events.
            if(oPart->cevents()->arefCount() <= 1)
            {
              if (oPart->lenTick() > len) {
                    EventList* el = nPart->events();
                    iEvent ie = el->lower_bound(len);
                    for (; ie != el->end();) {
                          iEvent i = ie;
                          ++ie;
                          // Indicate no undo, and do not do port controller values and clone parts.
                          //audio->msgDeleteEvent(i->second, nPart, false);
                          audio->msgDeleteEvent(i->second, nPart, false, false, false);
                          }
                    }
            }
            // Indicate no undo, and do port controller values but not clone parts.
            //audio->msgChangePart(oPart, nPart, false);
            audio->msgChangePart(oPart, nPart, false, true, false);
             */

            endUndo(SC_PART_MODIFIED);
        }
}/*}}}*/
Example #3
0
    HINLINE void operator()(
                            T_SpeciesStorage& speciesStorage,
                            const uint32_t currentStep,
                            const EventTask& eventInt,
                            EventTask& pushEvent,
                            EventTask& commEvent
                            ) const
    {
        typedef std::list<EventTask> EventList;
        EventList updateEventList;
        EventList commEventList;

        /* push all species */
        typedef typename PMacc::particles::traits::FilterByFlag
        <
            VectorAllSpecies,
            particlePusher<>
        >::type VectorSpeciesWithPusher;
        ForEach<VectorSpeciesWithPusher, particles::PushSpecies<bmpl::_1>, MakeIdentifier<bmpl::_1> > pushSpecies;
        pushSpecies(forward(speciesStorage), currentStep, eventInt, forward(updateEventList));

        /* join all push events */
        for (typename EventList::iterator iter = updateEventList.begin();
             iter != updateEventList.end();
             ++iter)
        {
            pushEvent += *iter;
        }

        /* call communication for all species */
        ForEach<VectorSpeciesWithPusher, particles::CommunicateSpecies<bmpl::_1>, MakeIdentifier<bmpl::_1> > communicateSpecies;
        communicateSpecies(forward(speciesStorage), forward(updateEventList), forward(commEventList));

        /* join all communication events */
        for (typename EventList::iterator iter = commEventList.begin();
             iter != commEventList.end();
             ++iter)
        {
            commEvent += *iter;
        }
    }
Example #4
0
void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2)
{
    int l1 = 0; // len of first new part (ticks or samples)
    int l2 = 0; // len of second new part

    int samplepos = tempomap.tick2frame(tickpos);

    {
            l1 = tickpos - part->tick();
            l2 = part->lenTick() - l1;
    }

    if (l1 <= 0 || l2 <= 0)
        return;

    p1 = newPart(part); // new left part
    p2 = newPart(part); // new right part

    // Added by Tim. p3.3.6
    //printf("Track::splitPart part ev %p sz:%d ref:%d p1 %p sz:%d ref:%d p2 %p sz:%d ref:%d\n", part->events(), part->events()->size(), part->events()->arefCount(), p1->events(), p1->events()->size(), p1->events()->arefCount(), p2->events(), p2->events()->size(), p2->events()->arefCount());

    {
            p1->setLenTick(l1);
            p2->setTick(tickpos);
            p2->setLenTick(l2);
    }

    p2->setSn(p2->newSn());

    EventList* se = part->events();
    EventList* de1 = p1->events();
    EventList* de2 = p2->events();

    p1->setColorIndex(part->colorIndex());
    p2->setColorIndex(part->colorIndex());

    {
        for (iEvent ie = se->begin(); ie != se->end(); ++ie)
        {
            Event event = ie->second.clone();
            int t = event.tick();
            if (t >= l1)
            {
                event.move(-l1);
                de2->add(event);
            }
            else
                de1->add(event);
        }
    }
}
Example #5
0
std::vector<double> beatTrack(const AgentParameters &params,
                              const EventList &events,
                              const EventList &beats)
      {
      AgentList agents;
      int count = 0;
      double beatTime = -1;
      if (!beats.empty()) {
            count = beats.size() - 1;
            EventList::const_iterator itr = beats.end();
            --itr;
            beatTime = itr->time;
            }
      if (count > 0) {        // tempo given by mean of initial beats
            double ioi = (beatTime - beats.begin()->time) / count;
            agents.push_back(new Agent(params, ioi));
            }
      else            // tempo not given; use tempo induction
            agents = Induction::beatInduction(params, events);

      if (!beats.empty()) {
            for (AgentList::iterator itr = agents.begin(); itr != agents.end(); ++itr) {
                  (*itr)->beatTime = beatTime;
                  (*itr)->beatCount = count;
                  (*itr)->events = beats;
                  }
            }
      agents.beatTrack(events, params, -1);

      Agent *best = agents.bestAgent();
      std::vector<double> resultBeatTimes;

      if (best) {
            best->fillBeats(beatTime);
            for (EventList::const_iterator itr = best->events.begin();
                        itr != best->events.end(); ++itr) {
                  resultBeatTimes.push_back(itr->time);
                  }
            }
      for (AgentList::iterator ai = agents.begin(); ai != agents.end(); ++ai) {
            delete *ai;
            }

      return resultBeatTimes;
      }
Example #6
0
void AgentList::beatTrack(const EventList &el,
                          const AgentParameters &params,
                          double stop)
      {
      EventList::const_iterator ei = el.begin();
      bool phaseGiven = !empty() && ((*begin())->beatTime >= 0); // if given for one, assume given for others
      while (ei != el.end()) {
            Event ev = *ei;
            ++ei;
            if ((stop > 0) && (ev.time > stop))
                  break;
            bool created = phaseGiven;
            double prevBeatInterval = -1.0;
                        // cc: Duplicate our list of agents, and scan through the
                        // copy.  This means we can safely add agents to our own
                        // list while scanning without disrupting our scan.  Each
                        // agent needs to be re-added to our own list explicitly
                        // (since it is modified by e.g. considerAsBeat)
            Container currentAgents = list;
            list.clear();
            for (Container::iterator ai = currentAgents.begin();
                        ai != currentAgents.end(); ++ai) {
                  Agent *currentAgent = *ai;
                  if (currentAgent->beatInterval != prevBeatInterval) {
                        if ((prevBeatInterval >= 0) && !created && (ev.time < 5.0)) {
                                          // Create new agent with different phase
                              Agent *newAgent = new Agent(params, prevBeatInterval);
                                          // This may add another agent to our list as well
                              newAgent->considerAsBeat(ev, *this);
                              add(newAgent);
                              }
                        prevBeatInterval = currentAgent->beatInterval;
                        created = phaseGiven;
                        }
                  if (currentAgent->considerAsBeat(ev, *this))
                        created = true;
                  add(currentAgent);
                  }           // loop for each agent
            removeDuplicates();
            }           // loop for each event
      }
Example #7
0
void EventCanvas::songChanged(int flags)/*{{{*/
{
    // Is it simply a midi controller value adjustment? Forget it.
    if (flags == SC_MIDI_CONTROLLER)
        return;

    if (flags & ~SC_SELECTION)
    {
        _items.clear();
        start_tick = MAXINT;
        end_tick = 0;
    _curPart = 0;

        for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p)
        {
            MidiPart* part = (MidiPart*) (p->second);
        if (part->sn() == _curPartId)
        _curPart = part;
            unsigned stick = part->tick();
            unsigned len = part->lenTick();
            unsigned etick = stick + len;
            if (stick < start_tick)
                start_tick = stick;
            if (etick > end_tick)
                end_tick = etick;

            EventList* el = part->events();
            for (iEvent i = el->begin(); i != el->end(); ++i)
            {
                Event e = i->second;
                if (e.isNote())
                {
                    addItem(part, e);
                }
            }
        }
    }

    Event event;
    MidiPart* part = 0;
    int x = 0;
    CItem* nevent = 0;

    int n = 0; // count selections
    for (iCItem k = _items.begin(); k != _items.end(); ++k)
    {
        Event ev = k->second->event();
        bool selected = ev.selected();
        if (selected)
        {
            k->second->setSelected(true);
            ++n;
            if (!nevent)
            {
                nevent = k->second;
                Event mi = nevent->event();
                curVelo = mi.velo();
            }
        }
    }
    start_tick = song->roundDownBar(start_tick);
    end_tick = song->roundUpBar(end_tick);

    if (n == 1)
    {
        x = nevent->x();
        event = nevent->event();
        part = (MidiPart*) nevent->part();
    if (_curPart != part)
        {
        _curPart = part;
        _curPartId = _curPart->sn();
            curPartChanged();
        }
    }
    emit selectionChanged(x, event, part);
    if (_curPart == 0)
    {
        _curPart = (MidiPart*) (editor->parts()->begin()->second);
        if(_curPart)
        {
            editor->setCurCanvasPart(_curPart);
        }
    }

    updateCItemsZValues();

    redraw();
}/*}}}*/
Example #8
0
AgentList Induction::beatInduction(const AgentParameters &params,
                                   const EventList &events)
      {
      int i, j, b, bestCount;
      bool submult;
      int intervals = 0;			// number of interval clusters
      std::vector<int> bestn;             // count of high-scoring clusters
      bestn.resize(topN);

      double ratio, err;
      int degree;
      int maxClusterCount = (int) ceil((maxIOI - minIOI) / clusterWidth);
      std::vector<double> clusterMean;
      clusterMean.resize(maxClusterCount);
      std::vector<int> clusterSize;
      clusterSize.resize(maxClusterCount);
      std::vector<int> clusterScore;
      clusterScore.resize(maxClusterCount);

      EventList::const_iterator ptr1, ptr2;
      Event e1, e2;
      ptr1 = events.begin();

      while (ptr1 != events.end()) {
            e1 = *ptr1;
            ++ptr1;
            ptr2 = events.begin();
            e2 = *ptr2;
            ++ptr2;
            while (e2 != e1 && ptr2 != events.end()) {
                  e2 = *ptr2;
                  ++ptr2;
                  }
            while (ptr2 != events.end()) {
                  e2 = *ptr2;
                  ++ptr2;
                  double ioi = e2.time - e1.time;
                  if (ioi < minIOI)		// skip short intervals
                        continue;
                  if (ioi > maxIOI)		// ioi too long
                        break;
                  for (b = 0; b < intervals; b++)		// assign to nearest cluster
                        if (std::fabs(clusterMean[b] - ioi) < clusterWidth) {
                              if ((b < intervals - 1) && (std::fabs(clusterMean[b + 1] - ioi)
                                                          < std::fabs(clusterMean[b] - ioi))) {
                                    b++;		// next cluster is closer
                                    }
                              clusterMean[b] = (clusterMean[b] * clusterSize[b] + ioi)
                                          / (clusterSize[b] + 1);
                              clusterSize[b]++;
                              break;
                              }
                  if (b == intervals) {         // no suitable cluster; create new one
                        if (intervals == maxClusterCount) {
                                                // System.err.println("Warning: Too many clusters");
                              continue;         // ignore this IOI
                              }
                        intervals++;
                        for ( ; (b > 0) && (clusterMean[b - 1] > ioi); b--) {
                              clusterMean[b] = clusterMean[b - 1];
                              clusterSize[b] = clusterSize[b - 1];
                              }
                        clusterMean[b] = ioi;
                        clusterSize[b] = 1;
                        }
                  }
            }
      for (b = 0; b < intervals; b++)	// merge similar intervals
                        // TODO: they are now in order, so don't need the 2nd loop
                        // TODO: check BOTH sides before averaging or upper gps don't work
            for (i = b + 1; i < intervals; i++)
                  if (std::fabs(clusterMean[b] - clusterMean[i]) < clusterWidth) {
                        clusterMean[b] = (clusterMean[b] * clusterSize[b] +
                                          clusterMean[i] * clusterSize[i]) /
                                    (clusterSize[b] + clusterSize[i]);
                        clusterSize[b] = clusterSize[b] + clusterSize[i];
                        --intervals;
                        for (j = i + 1; j <= intervals; j++) {
                              clusterMean[j - 1] = clusterMean[j];
                              clusterSize[j - 1] = clusterSize[j];
                              }
                        }
      if (intervals == 0)
            return AgentList();
      for (b = 0; b < intervals; b++)
            clusterScore[b] = 10 * clusterSize[b];
      bestn[0] = 0;
      bestCount = 1;

      for (b = 0; b < intervals; b++) {
            for (i = 0; i <= bestCount; i++) {
                  if (i < topN && (i == bestCount || clusterScore[b] > clusterScore[bestn[i]])) {
                        if (bestCount < topN)
                              bestCount++;
                        for (j = bestCount - 1; j > i; j--)
                              bestn[j] = bestn[j - 1];
                        bestn[i] = b;
                        break;
                        }
                  }
            }
      for (b = 0; b < intervals; b++) {         // score intervals
            for (i = b + 1; i < intervals; i++) {
                  ratio = clusterMean[b] / clusterMean[i];
                  submult = ratio < 1;
                  if (submult)
                        degree = (int) nearbyint(1 / ratio);
                  else
                        degree = (int) nearbyint(ratio);
                  if ((degree >= 2) && (degree <= 8)) {
                        if (submult)
                              err = std::fabs(clusterMean[b] * degree - clusterMean[i]);
                        else
                              err = std::fabs(clusterMean[b] - clusterMean[i] * degree);
                        if (err < (submult ? clusterWidth : clusterWidth * degree)) {
                              if (degree >= 5)
                                    degree = 1;
                              else
                                    degree = 6 - degree;
                              clusterScore[b] += degree * clusterSize[i];
                              clusterScore[i] += degree * clusterSize[b];
                              }
                        }
                  }
            }

      AgentList a;
      for (int index = 0; index < bestCount; index++) {
            b = bestn[index];
                              // Adjust it, using the size of super- and sub-intervals
            double newSum = clusterMean[b] * clusterScore[b];
            int newCount = clusterSize[b];
            int newWeight = clusterScore[b];

            for (i = 0; i < intervals; i++) {
                  if (i == b)
                        continue;
                  ratio = clusterMean[b] / clusterMean[i];
                  if (ratio < 1) {
                        degree = (int) nearbyint(1 / ratio);
                        if ((degree >= 2) && (degree <= 8)) {
                              err = std::fabs(clusterMean[b] * degree - clusterMean[i]);
                              if (err < clusterWidth) {
                                    newSum += clusterMean[i] / degree * clusterScore[i];
                                    newCount += clusterSize[i];
                                    newWeight += clusterScore[i];
                                    }
                              }
                        }
                  else {
                        degree = (int) nearbyint(ratio);
                        if ((degree >= 2) && (degree <= 8)) {
                              err = std::fabs(clusterMean[b] - degree * clusterMean[i]);
                              if (err < clusterWidth * degree) {
                                    newSum += clusterMean[i] * degree * clusterScore[i];
                                    newCount += clusterSize[i];
                                    newWeight += clusterScore[i];
                                    }
                              }
                        }
                  }
            double beat = newSum / newWeight;
                        // Scale within range ... hope the grouping isn't ternary :(
            while (beat < minIBI)		// Maximum speed
                  beat *= 2.0;
            while (beat > maxIBI)		// Minimum speed
                  beat /= 2.0;
            if (beat >= minIBI) {
                  a.push_back(new Agent(params, beat));
                  }
            }
      return a;
      }
Example #9
0
File: midi.cpp Project: faesong/oom
void Audio::initDevices()
{
	//
	// mark all used ports
	//
	bool activePorts[MIDI_PORTS];
	for (int i = 0; i < MIDI_PORTS; ++i)
		activePorts[i] = false;

	MidiTrackList* tracks = song->midis();
	for (iMidiTrack it = tracks->begin(); it != tracks->end(); ++it)
	{
		MidiTrack* track = *it;
		activePorts[track->outPort()] = true;
	}
	if (song->click())
		activePorts[clickPort] = true;

	//
	// test for explicit instrument initialization
	//

	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		if (!activePorts[i])
			continue;

		MidiPort* port = &midiPorts[i];
		MidiInstrument* instr = port->instrument();
		MidiDevice* md = port->device();

		if (instr && md)
		{
			EventList* events = instr->midiInit();
			if (events->empty())
				continue;
			for (iEvent ie = events->begin(); ie != events->end(); ++ie)
			{
				MidiPlayEvent ev(0, i, 0, ie->second);
				md->putEvent(ev);
			}
			activePorts[i] = false; // no standard initialization
		}
	}
	//
	// damit Midi-Devices, die mehrere Ports besitzen, wie z.B.
	// das Korg NS5R, nicht mehrmals zwischen GM und XG/GS hin und
	// hergeschaltet werden, wird zun�hst auf allen Ports GM
	// initialisiert, und dann erst XG/GS
	//

	// Standard initialization...
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		if (!activePorts[i])
			continue;
		MidiPort* port = &midiPorts[i];
		switch (song->mtype())
		{
			case MT_GS:
			case MT_UNKNOWN:
				break;
			case MT_GM:
			case MT_XG:
				port->sendGmOn();
				break;
		}
	}
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		if (!activePorts[i])
			continue;
		MidiPort* port = &midiPorts[i];
		switch (song->mtype())
		{
			case MT_UNKNOWN:
				break;
			case MT_GM:
				port->sendGmInitValues();
				break;
			case MT_GS:
				port->sendGsOn();
				port->sendGsInitValues();
				break;
			case MT_XG:
				port->sendXgOn();
				port->sendXgInitValues();
				break;
		}
	}
}
Example #10
0
File: midi.cpp Project: faesong/oom
void buildMidiEventList(EventList* del, const MPEventList* el, MidiTrack* track,
		int div, bool addSysexMeta, bool doLoops)
{
	int hbank = 0xff;
	int lbank = 0xff;
	int rpnh = -1;
	int rpnl = -1;
	int datah = 0;
	int datal = 0;
	int dataType = 0; // 0 : disabled, 0x20000 : rpn, 0x30000 : nrpn

	EventList mel;

	for (iMPEvent i = el->begin(); i != el->end(); ++i)
	{
		MidiPlayEvent ev = *i;
		if (!addSysexMeta && (ev.type() == ME_SYSEX || ev.type() == ME_META))
			continue;
		if (!(ev.type() == ME_SYSEX || ev.type() == ME_META
				|| ((ev.channel() == track->outChannel()) && (ev.port() == track->outPort()))))
			continue;
		unsigned tick = ev.time();
		// Added by Tim. p3.3.8

		// Added by T356.
		if (doLoops)
		{
			if (tick >= song->lPos().tick() && tick < song->rPos().tick())
			{
				int loopn = ev.loopNum();
				int loopc = audio->loopCount();
				int cmode = song->cycleMode(); // CYCLE_NORMAL, CYCLE_MIX, CYCLE_REPLACE
				// If we want REPLACE and the event was recorded in a previous loop,
				//  just ignore it. This will effectively ignore ALL previous loop events inside
				//  the left and right markers, regardless of where recording was started or stopped.
				// We want to keep any loop 0 note-offs from notes which crossed over the left marker.
				// To avoid more searching here, just keep ALL note-offs from loop 0, and let code below
				//  sort out and keep which ones had note-ons.
				if (!(ev.isNoteOff() && loopn == 0))
				{
					if (cmode == Song::CYCLE_REPLACE && loopn < loopc)
					{
						// Added by Tim. p3.3.8
						//printf("buildMidiEventList: CYCLE_REPLACE t:%d type:%d A:%d B:%d ln:%d lc:%d\n", tick, ev.type(), ev.dataA(), ev.dataB(), loopn, loopc);

						continue;
					}
					// If we want NORMAL, same as REPLACE except keep all events from the previous loop
					//  from rec stop position to right marker (and beyond).
					if (cmode == Song::CYCLE_NORMAL)
					{
						// Not sure of accuracy here. Adjust? Adjusted when used elsewhere?
						unsigned endRec = audio->getEndRecordPos().tick();
						if ((tick < endRec && loopn < loopc) || (tick >= endRec && loopn < (loopc - 1)))
						{
							// Added by Tim. p3.3.8
							//printf("buildMidiEventList: CYCLE_NORMAL t:%d type:%d A:%d B:%d ln:%d lc:%d\n", tick, ev.type(), ev.dataA(), ev.dataB(), loopn, loopc);

							continue;
						}
					}
				}
			}
		}

		Event e;
		switch (ev.type())
		{
			case ME_NOTEON:
				e.setType(Note);

				if (track->type() == Track::DRUM)
				{
					int instr = drumInmap[ev.dataA()];
					e.setPitch(instr);
				}
				else
				{
					e.setPitch(ev.dataA());
				}

				e.setVelo(ev.dataB());
				e.setLenTick(0);
				break;
			case ME_NOTEOFF:
				e.setType(Note);
				if (track->type() == Track::DRUM)
				{
					int instr = drumInmap[ev.dataA()];
					e.setPitch(instr);
				}
				else
					e.setPitch(ev.dataA());
				e.setVelo(0);
				e.setVeloOff(ev.dataB());
				e.setLenTick(0);
				break;
			case ME_POLYAFTER:
				e.setType(PAfter);
				e.setA(ev.dataA());
				e.setB(ev.dataB());
				break;
			case ME_CONTROLLER:
			{
				int val = ev.dataB();
				switch (ev.dataA())
				{
					case CTRL_HBANK:
						hbank = val;
						break;

					case CTRL_LBANK:
						lbank = val;
						break;

					case CTRL_HDATA:
						datah = val;
						// check if a CTRL_LDATA follows
						// e.g. wie have a 14 bit controller:
					{
						iMPEvent ii = i;
						++ii;
						bool found = false;
						for (; ii != el->end(); ++ii)
						{
							MidiPlayEvent ev = *ii;
							if (ev.type() == ME_CONTROLLER)
							{
								if (ev.dataA() == CTRL_LDATA)
								{
									// handle later
									found = true;
								}
								break;
							}
						}
						if (!found)
						{
							if (rpnh == -1 || rpnl == -1)
							{
								printf("parameter number not defined, data 0x%x\n", datah);
							}
							else
							{
								int ctrl = dataType | (rpnh << 8) | rpnl;
								e.setType(Controller);
								e.setA(ctrl);
								e.setB(datah);
							}
						}
					}
						break;

					case CTRL_LDATA:
						datal = val;

						if (rpnh == -1 || rpnl == -1)
						{
							printf("parameter number not defined, data 0x%x 0x%x, tick %d, channel %d\n",
									datah, datal, tick, track->outChannel());
							break;
						}
						// assume that the sequence is always
						//    CTRL_HDATA - CTRL_LDATA
						// eg. that LDATA is always send last

						e.setType(Controller);
						// 14 Bit RPN/NRPN
						e.setA((dataType + 0x30000) | (rpnh << 8) | rpnl);
						e.setB((datah << 7) | datal);
						break;

					case CTRL_HNRPN:
						rpnh = val;
						dataType = 0x30000;
						break;

					case CTRL_LNRPN:
						rpnl = val;
						dataType = 0x30000;
						break;

					case CTRL_HRPN:
						rpnh = val;
						dataType = 0x20000;
						break;

					case CTRL_LRPN:
						rpnl = val;
						dataType = 0x20000;
						break;

					default:
						e.setType(Controller);
						int ctl = ev.dataA();
						e.setA(ctl);

						if (track->type() == Track::DRUM)
						{
							// Is it a drum controller event, according to the track port's instrument?
							MidiController *mc = midiPorts[track->outPort()].drumController(ctl);
							if (mc)
								// Store an index into the drum map.
								e.setA((ctl & ~0xff) | drumInmap[ctl & 0x7f]);
						}

						e.setB(val);
						break;
				}
			}
				break;

			case ME_PROGRAM:
				e.setType(Controller);
				e.setA(CTRL_PROGRAM);
				e.setB((hbank << 16) | (lbank << 8) | ev.dataA());
				break;

			case ME_AFTERTOUCH:
				e.setType(CAfter);
				e.setA(ev.dataA());
				break;

			case ME_PITCHBEND:
				e.setType(Controller);
				e.setA(CTRL_PITCH);
				e.setB(ev.dataA());
				break;

			case ME_SYSEX:
				e.setType(Sysex);
				e.setData(ev.data(), ev.len());
				break;

			case ME_META:
			{
				const unsigned char* data = ev.data();
				switch (ev.dataA())
				{
					case 0x01: // Text
						if (track->comment().isEmpty())
							track->setComment(QString((const char*) data));
						else
							track->setComment(track->comment() + "\n" + QString((const char*) data));
						break;
					case 0x03: // Sequence-/TrackName
						track->setName(QString((char*) data));
						break;
					case 0x6: // Marker
					{
						unsigned ltick = CALC_TICK(tick); //(tick * config.division + div/2) / div;
						song->addMarker(QString((const char*) (data)), ltick, false);
					}
						break;
					case 0x5: // Lyrics
					case 0x8: // text
					case 0x9:
					case 0xa:
						break;

					case 0x0f: // Track Comment
						track->setComment(QString((char*) data));
						break;
					case 0x51: // Tempo
					{
						unsigned tempo = data[2] + (data[1] << 8) + (data[0] << 16);
						unsigned ltick = CALC_TICK(tick); // (unsigned(tick) * unsigned(config.division) + unsigned(div/2)) / unsigned(div);
						// After ca 10 mins 32 bits will not be enough... This expression has to be changed/factorized or so in some "sane" way...
						tempomap.addTempo(ltick, tempo);
					}
						break;
					case 0x58: // Time Signature
					{
						int timesig_z = data[0];
						int n = data[1];
						int timesig_n = 1;
						for (int i = 0; i < n; i++)
							timesig_n *= 2;
						int ltick = CALC_TICK(tick); //(tick * config.division + div/2) / div;
						///sigmap.add(ltick, timesig_z, timesig_n);
						AL::sigmap.add(ltick, AL::TimeSignature(timesig_z, timesig_n));
					}
						break;
					case 0x59: // Key Signature
						// track->scale.set(data[0]);
						// track->scale.setMajorMinor(data[1]);
						break;
					default:
						printf("unknown Meta 0x%x %d\n", ev.dataA(), ev.dataA());
				}
			}
				break;
		} // switch(ev.type()
		if (!e.empty())
		{
			e.setTick(tick);
			// Added by Tim. p3.3.8
			//printf("buildMidiEventList: mel adding t:%d type:%d A:%d B:%d C:%d\n", tick, e.type(), e.dataA(), e.dataB(), e.dataC());

			mel.add(e);
		}
	} // i != el->end()

	//---------------------------------------------------
	//    resolve NoteOff events
	//---------------------------------------------------

	//      for (iEvent i = mel.begin(); i != mel.end(); ++i) {
	//            Event event = i->second;
	//            if (event.isNote())
	//                  event.setLenTick(0);
	//            }

	// Added by Tim. p3.3.8

	// The loop is a safe way to delete while iterating.
	bool loop;
	do
	{
		loop = false;

		for (iEvent i = mel.begin(); i != mel.end(); ++i)
		{
			Event ev = i->second;
			if (ev.isNote())
			{
				if (ev.isNoteOff())
				{
					iEvent k;
					bool found = false;
					for (k = i; k != mel.end(); ++k)
					{
						Event event = k->second;
						if (event.tick() > ev.tick())
							break;
						if (event.isNoteOff(ev))
						{
							ev.setLenTick(1);
							ev.setVelo(event.velo());
							ev.setVeloOff(0);
							// Added by Tim. p3.3.8
							//printf("buildMidiEventList: found note off: event t:%d len:%d type:%d A:%d B:%d C:%d  ev t:%d len:%d type:%d A:%d B:%d C:%d\n", event.tick(), event.lenTick(), event.type(), event.dataA(), event.dataB(), event.dataC(), ev.tick(), ev.lenTick(), ev.type(), ev.dataA(), ev.dataB(), ev.dataC());

							found = true;
							break;
						}
					}
					if (!found)
					{
						printf("NOTE OFF without Note ON tick %d type %d  %d %d\n",
								ev.tick(), ev.type(), ev.pitch(), ev.velo());
					}
					else
					{
						mel.erase(k);

						// Changed by Tim. p3.3.8
						//continue;
						loop = true;
						break;

					}
				}
				// Added by Tim. p3.3.8

				// If the event length is not zero, it means the event and its
				//  note on/off have already been taken care of. So ignore it.
				if (ev.lenTick() != 0)
				{
					continue;
				}

				iEvent k;
				for (k = mel.lower_bound(ev.tick()); k != mel.end(); ++k)
				{
					Event event = k->second;
					if (ev.isNoteOff(event))
					{
						int t = k->first - i->first;
						if (t <= 0)
						{
							if (debugMsg)
							{
								printf("Note len is (%d-%d)=%d, set to 1\n",
										k->first, i->first, k->first - i->first);
								ev.dump();
								event.dump();
							}
							t = 1;
						}
						ev.setLenTick(t);
						ev.setVeloOff(event.veloOff());
						// Added by Tim. p3.3.8
						//printf("buildMidiEventList: set len and velOff: event t:%d len:%d type:%d A:%d B:%d C:%d  ev t:%d len:%d type:%d A:%d B:%d C:%d\n", event.tick(), event.lenTick(), event.type(), event.dataA(), event.dataB(), event.dataC(), ev.tick(), ev.lenTick(), ev.type(), ev.dataA(), ev.dataB(), ev.dataC());

						break;
					}
				}
				if (k == mel.end())
				{
					printf("-no note-off! %d pitch %d velo %d\n",
							ev.tick(), ev.pitch(), ev.velo());
					//
					// switch off at end of measure
					//
					int endTick = song->roundUpBar(ev.tick() + 1);
					ev.setLenTick(endTick - ev.tick());
				}
				else
				{
					mel.erase(k);
					// Added by Tim. p3.3.8
					loop = true;
					break;

				}
			}
		}
	} while (loop);

	// DEBUG: any note offs left?

	// Removed by Tim. p3.3.8
	//for (iEvent i = mel.begin(); i != mel.end(); ++i) {
	//      Event ev  = i->second;
	//      if (ev.isNoteOff()) {
	//            printf("+extra note-off! %d pitch %d velo %d\n",
	//                     i->first, ev.pitch(), ev.velo());
	//                  ev.dump();
	//            }
	//      }

	for (iEvent i = mel.begin(); i != mel.end(); ++i)
	{
		Event ev = i->second;
		if (ev.isNoteOff())
		{
			printf("+extra note-off! %d pitch %d velo %d\n",
					i->first, ev.pitch(), ev.velo());
			//                  ev.dump();
			continue;
		}
		int tick = CALC_TICK(ev.tick()); //(ev.tick() * config.division + div/2) / div;
		if (ev.isNote())
		{
			int lenTick = CALC_TICK(ev.lenTick()); //(ev.lenTick() * config.division + div/2) / div;
			ev.setLenTick(lenTick);
		}
		ev.setTick(tick);
		del->add(ev);
	}
}
Example #11
0
File: midi.cpp Project: faesong/oom
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;
}/*}}}*/
Example #12
0
File: part.cpp Project: faesong/oom
void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2)
{
	int l1 = 0; // len of first new part (ticks or samples)
	int l2 = 0; // len of second new part

	int samplepos = tempomap.tick2frame(tickpos);

	switch (type())
	{
		case WAVE:
			l1 = samplepos - part->frame();
			l2 = part->lenFrame() - l1;
			break;
		case MIDI:
		case DRUM:
			l1 = tickpos - part->tick();
			l2 = part->lenTick() - l1;
			break;
		default:
			return;
	}

	if (l1 <= 0 || l2 <= 0)
		return;

	p1 = newPart(part); // new left part
	p2 = newPart(part); // new right part

	// Added by Tim. p3.3.6
	//printf("Track::splitPart part ev %p sz:%d ref:%d p1 %p sz:%d ref:%d p2 %p sz:%d ref:%d\n", part->events(), part->events()->size(), part->events()->arefCount(), p1->events(), p1->events()->size(), p1->events()->arefCount(), p2->events(), p2->events()->size(), p2->events()->arefCount());

	switch (type())
	{
		case WAVE:
			p1->setLenFrame(l1);
			p2->setFrame(samplepos);
			p2->setLenFrame(l2);
			break;
		case MIDI:
		case DRUM:
			p1->setLenTick(l1);
			p2->setTick(tickpos);
			p2->setLenTick(l2);
			break;
		default:
			break;
	}

	p2->setSn(p2->newSn());

	EventList* se = part->events();
	EventList* de1 = p1->events();
	EventList* de2 = p2->events();

	if (type() == WAVE)
	{
		int ps = part->frame();
		int d1p1 = p1->frame();
		int d2p1 = p1->endFrame();
		int d1p2 = p2->frame();
		int d2p2 = p2->endFrame();
		for (iEvent ie = se->begin(); ie != se->end(); ++ie)
		{
			Event event = ie->second;
			int s1 = event.frame() + ps;
			int s2 = event.endFrame() + ps;

			if ((s2 > d1p1) && (s1 < d2p1))
			{
				Event si = event.mid(d1p1 - ps, d2p1 - ps);
				de1->add(si);
			}
			if ((s2 > d1p2) && (s1 < d2p2))
			{
				Event si = event.mid(d1p2 - ps, d2p2 - ps);
				de2->add(si);
			}
		}
	}
	else
	{
		for (iEvent ie = se->begin(); ie != se->end(); ++ie)
		{
			Event event = ie->second.clone();
			int t = event.tick();
			if (t >= l1)
			{
				event.move(-l1);
				de2->add(event);
			}
			else
				de1->add(event);
		}
	}
}
Example #13
0
File: part.cpp Project: faesong/oom
void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)
{
	switch (track->type())
	{
		case Track::WAVE:
		{
			WavePart* nPart = new WavePart(*(WavePart*) oPart);
			EventList* el = nPart->events();
			unsigned new_partlength = tempomap.deltaTick2frame(oPart->tick(), oPart->tick() + len);
			//printf("new partlength in frames: %d\n", new_partlength);

			// If new nr of frames is less than previous what can happen is:
			// -   0 or more events are beginning after the new final position. Those are removed from the part
			// -   The last event begins before new final position and ends after it. If so, it will be resized to end at new part length
			if (new_partlength < oPart->lenFrame())
			{
				startUndo();

				for (iEvent i = el->begin(); i != el->end(); i++)
				{
					Event e = i->second;
					unsigned event_startframe = e.frame();
					unsigned event_endframe = event_startframe + e.lenFrame();
					//printf("Event frame=%d, length=%d\n", event_startframe, event_length);
					if (event_endframe < new_partlength)
						continue;
					if (event_startframe > new_partlength)
					{ // If event start was after the new length, remove it from part
						// Indicate no undo, and do not do port controller values and clone parts.
						//audio->msgDeleteEvent(e, nPart, false);
						audio->msgDeleteEvent(e, nPart, false, false, false);
						continue;
					}
					if (event_endframe > new_partlength)
					{ // If this event starts before new length and ends after, shrink it
						Event newEvent = e.clone();
						newEvent.setLenFrame(new_partlength - event_startframe);
						// Indicate no undo, and do not do port controller values and clone parts.
						//audio->msgChangeEvent(e, newEvent, nPart, false);
						audio->msgChangeEvent(e, newEvent, nPart, false, false, false);
					}
				}
				nPart->setLenFrame(new_partlength);
				// Indicate no undo, and do not do port controller values and clone parts.
				//audio->msgChangePart(oPart, nPart, false);
				audio->msgChangePart(oPart, nPart, false, false, false);

				endUndo(SC_PART_MODIFIED);
			}
				// If the part is expanded there can be no additional events beginning after the previous final position
				// since those are removed if the part has been shrunk at some time (see above)
				// The only thing we need to check is the final event: If it has data after the previous final position,
				// we'll expand that event
			else
			{
				if (!el->empty())
				{
					iEvent i = el->end();
					i--;
					Event last = i->second;
					unsigned last_start = last.frame();
					SndFileR file = last.sndFile();
					if (file.isNull())
						return;

					unsigned clipframes = (file.samples() - last.spos()); // / file.channels();
					Event newEvent = last.clone();
					//printf("SndFileR samples=%d channels=%d event samplepos=%d clipframes=%d\n", file.samples(), file.channels(), last.spos(), clipframes);

					unsigned new_eventlength = new_partlength - last_start;
					if (new_eventlength > clipframes) // Shrink event length if new partlength exceeds last clip
						new_eventlength = clipframes;

					newEvent.setLenFrame(new_eventlength);
					startUndo();
					// Indicate no undo, and do not do port controller values and clone parts.
					//audio->msgChangeEvent(last, newEvent, nPart, false);
					audio->msgChangeEvent(last, newEvent, nPart, false, false, false);
				}
				else
				{
					startUndo();
				}

				nPart->setLenFrame(new_partlength);
				// Indicate no undo, and do not do port controller values and clone parts.
				//audio->msgChangePart(oPart, nPart, false);
				audio->msgChangePart(oPart, nPart, false, false, false);
				endUndo(SC_PART_MODIFIED);
			}
		}
			break;
		case Track::MIDI:
		case Track::DRUM:
		{
			startUndo();

			MidiPart* nPart = new MidiPart(*(MidiPart*) oPart);
			nPart->setLenTick(len);
			// Indicate no undo, and do port controller values but not clone parts.
			audio->msgChangePart(oPart, nPart, false, true, false);

			// cut Events in nPart
			// Changed by T356. Don't delete events if this is a clone part.
			// The other clones might be longer than this one and need these events.
			if (nPart->cevents()->arefCount() <= 1)
			{
				if (oPart->lenTick() > len)
				{
					EventList* el = nPart->events();
					iEvent ie = el->lower_bound(len);
					for (; ie != el->end();)
					{
						iEvent i = ie;
						++ie;
						// Indicate no undo, and do port controller values and clone parts.
						audio->msgDeleteEvent(i->second, nPart, false, true, true);
					}
				}
			}

			/*
			// cut Events in nPart
			// Changed by T356. Don't delete events if this is a clone part.
			// The other clones might be longer than this one and need these events.
			if(oPart->cevents()->arefCount() <= 1)
			{
			  if (oPart->lenTick() > len) {
					EventList* el = nPart->events();
					iEvent ie = el->lower_bound(len);
					for (; ie != el->end();) {
						  iEvent i = ie;
						  ++ie;
						  // Indicate no undo, and do not do port controller values and clone parts.
						  //audio->msgDeleteEvent(i->second, nPart, false);
						  audio->msgDeleteEvent(i->second, nPart, false, false, false);
						  }
					}
			}
			// Indicate no undo, and do port controller values but not clone parts.
			//audio->msgChangePart(oPart, nPart, false);
			audio->msgChangePart(oPart, nPart, false, true, false);
			 */

			endUndo(SC_PART_MODIFIED);
			break;
		}
		default:
			break;
	}
}
Example #14
0
PyObject* getParts(PyObject*, PyObject* args)
{
	TrackList* tracks = song->tracks();
	const char* trackname;
	if (!PyArg_ParseTuple(args, "s", &trackname))
	{
		return NULL;
	}

	PyObject* pyparts = Py_BuildValue("[]");
	for (ciTrack t = tracks->begin(); t != tracks->end(); ++t)
	{
		Track* track = *t;
		if (track->name() != trackname)
			continue;

		PartList* parts = track->parts();
		for (ciPart p = parts->begin(); p != parts->end(); p++)
		{
			Part* part = p->second;

			MidiPart* mpart = (MidiPart*) part;
			PyObject* pypart = PyDict_New();
			int tick = mpart->tick();
			int lentick = mpart->lenTick();
			int serialnr = mpart->sn();
			PyObject* pstrtick = Py_BuildValue("s", "tick");
			PyObject* pitick = Py_BuildValue("i", tick);
			PyObject* pstrid = Py_BuildValue("s", "id");
			PyObject* pstrserial = Py_BuildValue("i", serialnr);
			PyObject* pstrlen = Py_BuildValue("s", "len");
			PyObject* pstrtick2 = Py_BuildValue("i", lentick);

			PyDict_SetItem(pypart, pstrtick, pitick);
			PyDict_SetItem(pypart, pstrid, pstrserial);
			PyDict_SetItem(pypart, pstrlen, pstrtick2);

			Py_DECREF(pstrtick);
			Py_DECREF(pitick);
			Py_DECREF(pstrid);
			Py_DECREF(pstrserial);
			Py_DECREF(pstrlen);
			Py_DECREF(pstrtick2);

			// Pack midi events into list before wrapping it all up
			EventList* events = mpart->events();
			PyObject* pyevents = Py_BuildValue("[]");
			for (ciEvent e = events->begin(); e != events->end(); e++)
			{
				PyObject* pyevent = PyDict_New(); // The event structure - a dictionary with keys 'type','tick','data'

				const Event& event = e->second;
				unsigned tick = e->first;
				PyObject* eventdata = Py_BuildValue("[i,i,i]", event.dataA(), event.dataB(), event.dataC());
				PyObject* pstrdata = Py_BuildValue("s", "data");
				pstrtick = Py_BuildValue("s", "tick");
				PyObject* pitickval = Py_BuildValue("i", tick);
				PyDict_SetItem(pyevent, pstrdata, eventdata);
				PyDict_SetItem(pyevent, pstrtick, pitickval);
				Py_DECREF(eventdata);
				Py_DECREF(pstrdata);
				Py_DECREF(pstrtick);
				Py_DECREF(pitickval);

				switch (event.type())
				{
					case Note:
					{
						PyObject* pstrtype = Py_BuildValue("s", "type");
						PyObject* pstrnote = Py_BuildValue("s", "note");
						PyObject* pstrlen = Py_BuildValue("s", "len");
						PyObject* pilentick = Py_BuildValue("i", event.lenTick());
						PyDict_SetItem(pyevent, pstrtype, pstrnote);
						PyDict_SetItem(pyevent, pstrlen, pilentick);
						Py_DECREF(pstrtype);
						Py_DECREF(pstrnote);
						Py_DECREF(pstrlen);
						Py_DECREF(pilentick);
						break;
					}
					case Controller:
					{
						PyObject* pstrtype = Py_BuildValue("s", "type");
						PyObject* pstrctrl = Py_BuildValue("s", "ctrl");
						PyDict_SetItem(pyevent, pstrtype, pstrctrl);
						Py_DECREF(pstrtype);
						Py_DECREF(pstrctrl);
						break;
					}
					default:
						printf("Event type not supported yet: %d\n", event.type());
						break;
				}
				PyList_Append(pyevents, pyevent);
				Py_DECREF(pyevent);
			}
			Py_DECREF(pyevents);
			// Add the event list to the pypart dictionary
			PyObject* pystrevents = Py_BuildValue("s", "events");
			PyDict_SetItem(pypart, pystrevents, pyevents);
			Py_DECREF(pystrevents);
			PyList_Append(pyparts, pypart);
			Py_DECREF(pypart);
		}

		return pyparts;
	}

	return NULL;
}
Example #15
0
QMimeData* EventCanvas::getTextDrag()
{
    //---------------------------------------------------
    //   generate event list from selected events
    //---------------------------------------------------

    EventList el;
    unsigned startTick = MAXINT;
    for (iCItem i = _items.begin(); i != _items.end(); ++i)
    {
        if (!i->second->isSelected())
            continue;
        ///NEvent* ne = (NEvent*)(i->second);
        CItem* ne = i->second;
        Event e = ne->event();
        if (startTick == MAXINT)
            startTick = e.tick();
        el.add(e);
    }

    //---------------------------------------------------
    //    write events as XML into tmp file
    //---------------------------------------------------

    FILE* tmp = tmpfile();
    if (tmp == 0)
    {
        fprintf(stderr, "EventCanvas::getTextDrag() fopen failed: %s\n",
                strerror(errno));
        return 0;
    }
    Xml xml(tmp);

    int level = 0;
    xml.tag(level++, "eventlist");
    for (ciEvent e = el.begin(); e != el.end(); ++e)
        e->second.write(level, xml, -startTick);
    xml.etag(--level, "eventlist");

    //---------------------------------------------------
    //    read tmp file into drag Object
    //---------------------------------------------------

    fflush(tmp);
    struct stat f_stat;
    if (fstat(fileno(tmp), &f_stat) == -1)
    {
        fprintf(stderr, "PianorollCanvas::copy() fstat failes:<%s>\n",
                strerror(errno));
        fclose(tmp);
        return 0;
    }
    int n = f_stat.st_size;
    char* fbuf = (char*) mmap(0, n + 1, PROT_READ | PROT_WRITE,
                              MAP_PRIVATE, fileno(tmp), 0);
    fbuf[n] = 0;

    QByteArray data(fbuf);
    QMimeData* md = new QMimeData();
    //QDrag* drag = new QDrag(parent);

    md->setData("text/x-los-eventlist", data);
    //drag->setMimeData(md);

    munmap(fbuf, n);
    fclose(tmp);

    //return drag;
    return md;
}
Example #16
0
void LOS::processTrack(MidiTrack* track)
{
    EventList* tevents = track->events();
    if (tevents->empty())
        return;

    //---------------------------------------------------
    // Identify Parts
    // The MIDI tracks are broken up into parts
    // A new Part will be located based on track.
    // Events will be aligned on new track
    //---------------------------------------------------

    PartList* pl = track->parts();

    int lastTick = 0;
    for (iEvent i = tevents->begin(); i != tevents->end(); ++i)
    {
        Event event = i->second;
        int epos = event.tick() + event.lenTick();
        if (epos > lastTick)
            lastTick = epos;
    }

    QString partname = track->name();
    int len = song->roundUpBar(lastTick + 1);

    // p3.3.27
    if (config.importMidiSplitParts)
    {

        int bar2, beat;
        unsigned tick;
        sigmap.tickValues(len, &bar2, &beat, &tick);

        int lastOff = 0;
        int st = -1; // start tick current part
        int x1 = 0; // start tick current measure
        int x2 = 0; // end tick current measure

        for (int bar = 0; bar < bar2; ++bar, x1 = x2)
        {
            ///x2 = sigmap.bar2tick(bar+1, 0, 0);
            x2 = sigmap.bar2tick(bar + 1, 0, 0);
            if (lastOff > x2)
            {
                // this measure is busy!
                continue;
            }
            iEvent i1 = tevents->lower_bound(x1);
            iEvent i2 = tevents->lower_bound(x2);

            if (i1 == i2)
            { // empty?
                if (st != -1)
                {
                    MidiPart* part = new MidiPart(track);
                    part->setTick(st);
                    part->setLenTick(x1 - st);
                    // printf("new part %d len: %d\n", st, x1-st);
                    part->setName(partname);
                    pl->add(part);
                    st = -1;
                }
            }
            else
            {
                if (st == -1)
                    st = x1; // begin new  part
                //HACK:
                //lastOff:
                for (iEvent i = i1; i != i2; ++i)
                {
                    Event event = i->second;
                    if (event.type() == Note)
                    {
                        int off = event.tick() + event.lenTick();
                        if (off > lastOff)
                            lastOff = off;
                    }
                }
            }
        }
        if (st != -1)
        {
            MidiPart* part = new MidiPart(track);
            part->setTick(st);
            // printf("new part %d len: %d\n", st, x2-st);
            part->setLenTick(x2 - st);
            part->setName(partname);
            pl->add(part);
        }
    }
    else
    {
        // Just one long part...
        MidiPart* part = new MidiPart(track);
        //part->setTick(st);
        part->setTick(0);
        part->setLenTick(len);
        part->setName(partname);
        pl->add(part);
    }

    //-------------------------------------------------------------
    //    assign events to parts
    //-------------------------------------------------------------

    for (iPart p = pl->begin(); p != pl->end(); ++p)
    {
        MidiPart* part = (MidiPart*) (p->second);
        int stick = part->tick();
        int etick = part->tick() + part->lenTick();
        iEvent r1 = tevents->lower_bound(stick);
        iEvent r2 = tevents->lower_bound(etick);
        int startTick = part->tick();

        EventList* el = part->events();
        for (iEvent i = r1; i != r2; ++i)
        {
            Event ev = i->second;
            int ntick = ev.tick() - startTick;
            ev.setTick(ntick);
            el->add(ev);
        }
        tevents->erase(r1, r2);
    }

    if (tevents->size())
        printf("-----------events left: %zd\n", tevents->size());
    for (iEvent i = tevents->begin(); i != tevents->end(); ++i)
    {
        printf("%d===\n", i->first);
        i->second.dump();
    }
    // all events should be processed:
    assert(tevents->empty());
}
Example #17
0
void EventCanvas::pasteAt(const QString& pt, int pos)
{
    QByteArray ba = pt.toLatin1();
    const char* p = ba.constData();
    Xml xml(p);
    for (;;)
    {
        Xml::Token token = xml.parse();
        const QString& tag = xml.s1();
        switch (token)
        {
        case Xml::Error:
        case Xml::End:
            return;
        case Xml::TagStart:
            if (tag == "eventlist")
            {
                song->startUndo();
                EventList* el = new EventList();
                el->read(xml, "eventlist");
                int modified = SC_EVENT_INSERTED;
                for (iEvent i = el->begin(); i != el->end(); ++i)
                {
                    Event e = i->second;
                    int tick = e.tick() + pos - _curPart->tick();
                    if (tick < 0)
                    {
                        printf("ERROR: trying to add event before current part!\n");
                        song->endUndo(SC_EVENT_INSERTED);
                        delete el;
                        return;
                    }

                    e.setTick(tick);
                    int diff = e.endTick() - _curPart->lenTick();
                    if (diff > 0)
                    {// too short part? extend it
                        Part* newPart = _curPart->clone();
                        newPart->setLenTick(newPart->lenTick() + diff);
                        // Indicate no undo, and do port controller values but not clone parts.
                        audio->msgChangePart(_curPart, newPart, false, true, false);
                        modified = modified | SC_PART_MODIFIED;
                        _curPart = newPart; // reassign
                    }
                    // Indicate no undo, and do not do port controller values and clone parts.
                    audio->msgAddEvent(e, _curPart, false, false, false);
                }
                song->endUndo(modified);
                delete el;
                return;
            }
            else
                xml.unknown("pasteAt");
            break;
            case Xml::Attribut:
            case Xml::TagEnd:
            default:
            break;
        }
    }
}
Example #18
0
bool LOS::importMidi(const QString name, bool merge)/*{{{*/
{
    bool popenFlag;
    FILE* fp = fileOpen(this, name, QString(".mid"), "r", popenFlag);
    if (fp == 0)
        return true;
    MidiFile mf(fp);
    bool rv = mf.read();
    popenFlag ? pclose(fp) : fclose(fp);
    if (rv)
    {
        QString s(tr("reading midifile\n  "));
        s += name;
        s += tr("\nfailed: ");
        s += mf.error();
        QMessageBox::critical(this, QString("LOS"), s);
        return rv;
    }
    //
    //  evaluate song Type (GM, XG, GS, unknown)
    //
    MType t = song->midiType();
    if (!merge)
    {
        t = mf.mtype();
        song->setMType(t);
    }
    MidiInstrument* instr = 0;
    for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
    {
        MidiInstrument* mi = *i;
        if ((mi->iname() == "GM" && ((t == MT_UNKNOWN) || (t == MIDI_TYPE_GM)))
                || ((mi->iname() == "GS") && (t == MT_GS))
                || ((mi->iname() == "XG") && (t == MT_XG)))
        {
            instr = mi;
            break;
        }
    }
    if (instr == 0)
    {
        // the standard instrument files (GM, GS, XG) must be present
        printf("no instrument, type %d\n", t);
        return true;
        //abort();
    }

    MidiFileTrackList* etl = mf.trackList();
    int division = mf.division();

    //
    // create MidiTrack and copy events to ->events()
    //    - combine note on/off events
    //    - calculate tick value for internal resolution
    //
    for (iMidiFileTrack t = etl->begin(); t != etl->end(); ++t)
    {
        MPEventList* el = &((*t)->events);
        if (el->empty())
            continue;
        //
        // if we split the track, SYSEX and META events go into
        // the first target track

        bool first = true;
        // somewhat silly and slooow:
        for (int port = 0; port < kMaxMidiPorts; ++port)
        {
            for (int channel = 0; channel < kMaxMidiChannels; ++channel)
            {
                //
                // check if there are any events for port/channel in track:
                //
                iMPEvent i;
                for (i = el->begin(); i != el->end(); ++i)
                {
                    MidiPlayEvent ev = *i;
                    if (ev.type() != ME_SYSEX && ev.type() != ME_META
                            && ev.channel() == channel && ev.port() == port)
                        break;
                }
                if (i == el->end())
                    continue;
                MidiTrack* track = new MidiTrack();
                if ((*t)->isDrumTrack)
                {
                    track->setType(Track::DRUM);
                }

                track->setOutChannel(channel);
                track->setOutPort(port);

                MidiPort* mport = &midiPorts[track->outPort()];
                // this overwrites any instrument set for this port:
                mport->setInstrument(instr);

                EventList* mel = track->events();
                //buildMidiEventList(mel, el, track, division, first);
                // Don't do loops.
                buildMidiEventList(mel, el, track, division, first, false);
                first = false;

                // Hmm. buildMidiEventList already takes care of this.
                // But it seems to work. How? Must test.
                if (channel == 9 && song->midiType() != MT_UNKNOWN)
                {
                    track->setType(Track::DRUM);
                    //
                    // remap drum pitch with drumInmap
                    //
                    EventList* tevents = track->events();
                    for (iEvent i = tevents->begin(); i != tevents->end(); ++i)
                    {
                        Event ev = i->second;
                        if (ev.isNote())
                        {
                            int pitch = drumInmap[ev.pitch()];
                            ev.setPitch(pitch);
                        }
                        else
                            if (ev.type() == Controller)
                        {
                            int ctl = ev.dataA();
                            MidiController *mc = mport->drumController(ctl);
                            if (mc)
                                ev.setA((ctl & ~0xff) | drumInmap[ctl & 0x7f]);
                        }
                    }
                }

                processTrack(track);

                song->insertTrack(track, -1);
            }
        }
        if (first)
        {
            //
            // track does only contain non-channel messages
            // (SYSEX or META)
            //
            MidiTrack* track = new MidiTrack();
            track->setOutChannel(0);
            track->setOutPort(0);
            EventList* mel = track->events();
            //buildMidiEventList(mel, el, track, division, true);
            // Do SysexMeta. Don't do loops.
            buildMidiEventList(mel, el, track, division, true, false);
            processTrack(track);
            song->insertTrack(track, -1);
        }
    }

    if (!merge)
    {
        TrackList* tl = song->tracks();
        if (!tl->empty())
        {
            Track* track = tl->front();
            track->setSelected(true);
        }
        song->initLen();

        int z, n;
        ///sigmap.timesig(0, z, n);
        sigmap.timesig(0, z, n);

        int tempo = tempomap.tempo(0);
        transport->setTimesig(z, n);
        transport->setTempo(tempo);

        bool masterF = !tempomap.empty();
        song->setMasterFlag(masterF);
        transport->setMasterFlag(masterF);

        song->updatePos();

        composer->reset();
        ///composer->setMode(int(song->midiType())); // p4.0.7 Tim
    }
    else
    {
        song->initLen();
    }

    return false;
}/*}}}*/
Example #19
0
void CSystemEvents::ExecuteEvents()
{
	EventList Events;
	{
		CGuard Guard(m_CS);

		m_bDoSomething = false;
		if (m_Events.size() == 0)
		{
			return;
		}
	
		Events = m_Events;
		m_Events.clear();
	}

	bool bPause = false, bLoadedSave = false;
	for (EventList::const_iterator iter = Events.begin(); !bLoadedSave && iter != Events.end(); iter++ )
	{
		switch (*iter)
		{
		case SysEvent_CloseCPU:
			m_System->m_EndEmulation = true;
			break;
		case SysEvent_ResetCPU_Soft:
			m_System->GameReset();
			break;
		case SysEvent_ResetCPU_SoftDone:
			m_System->Reset(true,false);
			break;
		case SysEvent_ResetCPU_Hard:
			m_System->Reset(true,true);
			break;
		case SysEvent_Profile_GenerateLogs:
			m_System->m_Profile.GenerateLog();
			break;
		case SysEvent_Profile_StartStop:
		case SysEvent_Profile_ResetLogs:
			m_System->m_Profile.ResetCounters();
			break;
		case SysEvent_ExecuteInterrupt:
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_Interrupt_SP:
			g_Reg->MI_INTR_REG |= MI_INTR_SP;
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_Interrupt_SI:
			g_Reg->MI_INTR_REG |= MI_INTR_SI;
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_Interrupt_AI:
			g_Reg->MI_INTR_REG |= MI_INTR_AI;
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_Interrupt_VI:
			g_Reg->MI_INTR_REG |= MI_INTR_VI;
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_Interrupt_PI:
			g_Reg->MI_INTR_REG |= MI_INTR_PI;
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_Interrupt_DP:
			g_Reg->MI_INTR_REG |= MI_INTR_DP;
			g_Reg->DoIntrException(false);
			break;
		case SysEvent_SaveMachineState:
			if (!m_System->SaveState()) 
			{
				m_Events.push_back(SysEvent_SaveMachineState);
				m_bDoSomething = true;
			}
			break;
		case SysEvent_LoadMachineState:
			if (m_System->LoadState())
			{
				bLoadedSave = true;
			}
			break;
		case SysEvent_ChangePlugins:
			ChangePluginFunc();
			break;
		case SysEvent_ChangingFullScreen:
			Notify().ChangeFullScreen();
			break;
		case SysEvent_GSButtonPressed:
			if (m_System->m_Cheats.CheatsSlectionChanged())
			{
				m_System->m_Cheats.LoadCheats(false, m_Plugins);
			}
			m_System->m_Cheats.ApplyGSButton(g_MMU);
			break;
		case SysEvent_PauseCPU_FromMenu:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_FromMenu);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_AppLostFocus:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_AppLostFocus);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_AppLostActive:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_AppLostActive);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_SaveGame:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_SaveGame);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_LoadGame:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_LoadGame);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_DumpMemory:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_DumpMemory);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_SearchMemory:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_SearchMemory);
				bPause = true;
			}
			break;
		case SysEvent_PauseCPU_Settings:
			if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
			{
				g_Settings->SaveBool(GameRunning_CPU_Paused,true);
				g_Settings->SaveDword(GameRunning_CPU_PausedType, PauseType_Settings);
				bPause = true;
			}
			break;
		default:
			g_Notify->BreakPoint(__FILEW__,__LINE__);
			break;
		}
	}

	if (bPause)
	{
		m_System->Pause();
	}
}
Example #20
0
void ListEdit::songChanged(int type)
{
    if (type == 0)
        return;
    if (type & (SC_PART_REMOVED | SC_PART_MODIFIED
            | SC_PART_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED
            | SC_EVENT_INSERTED | SC_SELECTION))
    {
        if (type & (SC_PART_REMOVED | SC_PART_INSERTED))
            genPartlist();
        // close window if editor has no parts anymore
        if (parts()->empty())
        {
            close();
            return;
        }
        liste->setSortingEnabled(false);
        if (type == SC_SELECTION)
        {
            bool update = false;
            QTreeWidgetItem* ci = 0;
            liste->blockSignals(true);
            for (int row = 0; row < liste->topLevelItemCount(); ++row)
            {
                QTreeWidgetItem* i = liste->topLevelItem(row);
                if (i->isSelected() ^ ((EventListItem*) i)->event.selected())
                {
                    i->setSelected(((EventListItem*) i)->event.selected());
                    if (i->isSelected())
                        ci = i;
                    update = true;
                }
            }
            if (update)
            {
                if (ci)
                {
                    liste->setCurrentItem(ci);
                    liste->scrollToItem(ci, QAbstractItemView::EnsureVisible);
                }
                //liste->update();
            }
            liste->blockSignals(false);
        }
        else
        {
            curPart = 0;
            curTrack = 0;
            liste->clear();
            for (iPart p = parts()->begin(); p != parts()->end(); ++p)
            {
                MidiPart* part = (MidiPart*) (p->second);
                if (part->sn() == curPartId)
                    curPart = part;
                EventList* el = part->events();
                for (iEvent i = el->begin(); i != el->end(); ++i)
                {
                    EventListItem* item = new EventListItem(liste, i->second, part);
                    for (int col = 0; col < liste->columnCount(); ++col)
                        item->setText(col, item->text(col));
                    item->setSelected(i->second.selected());
                    if (item->event.tick() == (unsigned) selectedTick)
                    { //prevent compiler warning: comparison of signed/unsigned)
                        liste->setCurrentItem(item);
                        item->setSelected(true);
                        liste->scrollToItem(item, QAbstractItemView::EnsureVisible);
                    }
                }
            }
        }

        // p3.3.34
        //if (curPart == 0)
        //      curPart  = (MidiPart*)(parts()->begin()->second);
        //curTrack = curPart->track();
        if (!curPart)
        {
            if (!parts()->empty())
            {
                curPart = (MidiPart*) (parts()->begin()->second);
                if (curPart)
                    curTrack = curPart->track();
                else
                    curPart = 0;
            }
        }
    }
    liste->setSortingEnabled(true);
}