コード例 #1
0
ファイル: mess.cpp プロジェクト: OpenGanesh/oom
bool Mess::processEvent(const MidiPlayEvent& ev)
      {
      switch(ev.type()) {
            case ME_NOTEON:
                  return playNote(ev.channel(), ev.dataA(), ev.dataB());
            case ME_NOTEOFF:
                  return playNote(ev.channel(), ev.dataA(), 0);
            case ME_SYSEX:
	            return sysex(ev.len(), ev.data());
            case ME_CONTROLLER:
                  return setController(ev.channel(), ev.dataA(), ev.dataB());
            case ME_PITCHBEND:       // Tim.
                  return setController(ev.channel(), CTRL_PITCH, ev.dataA());
            }
      return false;
      }
コード例 #2
0
ファイル: jackmidi.cpp プロジェクト: ViktorNova/los
bool MidiJackDevice::queueEvent(const MidiPlayEvent& e)
{
    if (!_out_client_jackport) // p3.3.55
        return false;
    void* pb = jack_port_get_buffer(_out_client_jackport, segmentSize); // p3.3.55

    int frameOffset = audio->getFrameOffset();
    unsigned pos = audio->pos().frame();
    int ft = e.time() - frameOffset - pos;

    if (ft < 0)
        ft = 0;
    if (ft >= (int) segmentSize)
    {
        if(debugMsg)
            printf("MidiJackDevice::queueEvent: Event time:%d out of range. offset:%d ft:%d (seg=%d)\n", e.time(), frameOffset, ft, segmentSize);
        if (ft > (int) segmentSize)
            ft = segmentSize - 1;
    }

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

    switch (e.type())
    {
        case ME_NOTEON:
        case ME_NOTEOFF:
        case ME_POLYAFTER:
        case ME_CONTROLLER:
        case ME_PITCHBEND:
        {
#ifdef JACK_MIDI_DEBUG
            printf("MidiJackDevice::queueEvent note on/off polyafter controller or pitch\n");
#endif

            unsigned char* p = jack_midi_event_reserve(pb, ft, 3);
            if (p == 0)
            {
                #ifdef JACK_MIDI_DEBUG
                fprintf(stderr, "MidiJackDevice::queueEvent NOTE CONTROL PAT or PB: buffer overflow, stopping until next cycle\n");
                #endif
                return false;
            }
            p[0] = e.type() | e.channel();
            p[1] = e.dataA();
            p[2] = e.dataB();
        }
            break;

        case ME_PROGRAM:
        case ME_AFTERTOUCH:
        {
#ifdef JACK_MIDI_DEBUG
            printf("MidiJackDevice::queueEvent program or aftertouch\n");
#endif

            unsigned char* p = jack_midi_event_reserve(pb, ft, 2);
            if (p == 0)
            {
                #ifdef JACK_MIDI_DEBUG
                fprintf(stderr, "MidiJackDevice::queueEvent PROG or AT: buffer overflow, stopping until next cycle\n");
                #endif
                return false;
            }
            p[0] = e.type() | e.channel();
            p[1] = e.dataA();
        }
            break;
        case ME_SYSEX:
        {
#ifdef JACK_MIDI_DEBUG
            printf("MidiJackDevice::queueEvent sysex\n");
#endif

            const unsigned char* data = e.data();
            int len = e.len();
            unsigned char* p = jack_midi_event_reserve(pb, ft, len + 2);
            if (p == 0)
            {
                fprintf(stderr, "MidiJackDevice::queueEvent ME_SYSEX: buffer overflow, sysex too big, event lost\n");
                return true;
            }
            p[0] = 0xf0;
            p[len + 1] = 0xf7;
            memcpy(p + 1, data, len);
        }
            break;
        case ME_SONGPOS:
        case ME_CLOCK:
        case ME_START:
        case ME_CONTINUE:
        case ME_STOP:
            if(debugMsg)
                printf("MidiJackDevice::queueEvent: event type %x not supported\n", e.type());
            return true;
            break;
    }

    return true;
}
コード例 #3
0
ファイル: midi.cpp プロジェクト: 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);
	}
}
コード例 #4
0
ファイル: fluidsynthgui.cpp プロジェクト: faesong/oom
void FluidSynthGui::processEvent(const MidiPlayEvent& ev)
      {
      //Sysexes sent from the client
      if (ev.type() == ME_SYSEX) {
            byte* data = ev.data();
            switch (*data) {
                  case FS_LASTDIR_CHANGE:
                        lastdir = QString((const char*)data+1);
                        break;
                  case FS_ERROR: {
                        char* msg = (char*) (data+1);
                        
                        printf("OOMidi: fluidsynth error: %s\n", msg);
                        
                        break;
                        }
                  case FS_SEND_SOUNDFONTDATA: {
                        int chunk_len;
                        int filename_len;

                        int count = (int)*(data+1); //Number of elements
                        byte* cp = data+2; //Point to beginning of first chunk
                        sfListView->clear(); //Clear the listview
                        stack.clear(); //Clear the stack since we're starting over again

                        while (count) {
                              FluidGuiSoundFont font;
                              filename_len = strlen((const char*)cp) + 1;
                              font.name = (const char*)cp;
                              font.id = *(cp + filename_len);
                              chunk_len = filename_len + FS_SFDATALEN;
                              stack.push_front(font);
                              cp += chunk_len; //Move to next chunk
                              count--;
                              }
                        updateSoundfontListView();
                        updateChannelListView();
                        break;
                        }
                  case FS_SEND_CHANNELINFO: {
                        byte* chptr = (data+1);
                        for (int i=0; i< FS_MAX_NR_OF_CHANNELS; i++) {
                              byte id = *chptr;
                              byte channel = *(chptr+1);
                              channels[channel] = id;
                              chptr+=2;
                              }
                        updateChannelListView();

                        break;
                        }
                  case FS_SEND_DRUMCHANNELINFO: {
                        byte* drumchptr = (data+1);
                        for (int i=0; i<FS_MAX_NR_OF_CHANNELS; i++) {
                              drumchannels[i] = *drumchptr;
                              drumchptr++;
                              }
                        updateChannelListView();
                        break;
                        }
                  default:
                        if (FS_DEBUG)
                              printf("FluidSynthGui::processEvent() : Unknown Sysex received: %d\n", ev.type());
                        break;
                  }
            }
            //Controllers sent from the client:
      else
            if(ev.type() == ME_CONTROLLER) {
                  int id = ev.dataA();
                  int val = ev.dataB();
                  switch (id) {
                        case FS_GAIN: {
                              bool sb = Gain->signalsBlocked();
                              Gain->blockSignals(true);
                              // Update Gain-slider without causing it to respond to it's own signal (and send another msg to the synth)
                              Gain->setValue(val);
                              Gain->blockSignals(sb);
                              break;
                              }
                        case FS_REVERB_ON: {
                              bool sb = Reverb->signalsBlocked();
                              Reverb->blockSignals(true);
                              Reverb->setChecked(val);
                              Reverb->blockSignals(sb);
                              break;
                              }
                        case FS_REVERB_LEVEL: {
                              bool sb = ReverbLevel->signalsBlocked();
                              ReverbLevel->blockSignals(true);
                              ReverbLevel->setValue(val);
                              ReverbLevel->blockSignals(sb);
                              break;
                              }
                        case FS_REVERB_DAMPING: {
                              bool sb = ReverbDamping->signalsBlocked();
                              ReverbDamping->blockSignals(true);
                              ReverbDamping->setValue(val);
                              ReverbDamping->blockSignals(sb);
                              break;
                              }
                        case FS_REVERB_ROOMSIZE: {
                              bool sb = ReverbRoomSize->signalsBlocked();
                              ReverbRoomSize->blockSignals(true);
                              ReverbRoomSize->setValue(val);
                              ReverbRoomSize->blockSignals(sb);
                              break;
                              }
                        case FS_REVERB_WIDTH: {
                              bool sb = ReverbWidth->signalsBlocked();
                              ReverbWidth->blockSignals(true);
                              ReverbWidth->setValue(val);
                              ReverbWidth->blockSignals(sb);
                              break;
                              }
                        case FS_CHORUS_ON: {
                              Chorus->blockSignals(true);
                              Chorus->setChecked(val);
                              Chorus->blockSignals(false);
                              break;
                              }
                        case FS_CHORUS_SPEED: {
                              ChorusSpeed->blockSignals(true);
                              ChorusSpeed->setValue(val);
                              ChorusSpeed->blockSignals(false);
                              break;
                              }
                        case FS_CHORUS_NUM: {
                              ChorusNumber->blockSignals(true);
                              ChorusNumber->setValue(val);
                              ChorusNumber->blockSignals(false);
                              break;
                              }
                        case FS_CHORUS_TYPE: {
                              ChorusType->blockSignals(true);
                              ChorusType->setCurrentIndex(val);
                              ChorusType->blockSignals(false);
                              break;
                              }
                        case FS_CHORUS_DEPTH: {
                              ChorusDepth->blockSignals(true);
                              ChorusDepth->setValue(val);
                              ChorusDepth->blockSignals(false);
                              break;
                              }
                        case FS_CHORUS_LEVEL: {
                              ChorusLevel->blockSignals(true);
                              ChorusLevel->setValue(val);
                              ChorusLevel->blockSignals(false);
                              break;
                              }
                        default:
                              if (FS_DEBUG)
                                    printf("FluidSynthGui::processEvent() : Unknown controller sent to gui: %x\n",id);
                              break;
                        }
                  }
      else
            if (FS_DEBUG)
                  printf("FluidSynthGui::processEvent - unknown event of type %dreceived from synth.\n", ev.type());
      }