Esempio n. 1
0
void Synthesiser::handleMidiEvent (const MidiMessage& m)
{
    if (m.isNoteOn())
    {
        noteOn (m.getChannel(),
                m.getNoteNumber(),
                m.getFloatVelocity());
    }
    else if (m.isNoteOff())
    {
        noteOff (m.getChannel(),
                 m.getNoteNumber(),
                 true);
    }
    else if (m.isAllNotesOff() || m.isAllSoundOff())
    {
        allNotesOff (m.getChannel(), true);
    }
    else if (m.isPitchWheel())
    {
        const int channel = m.getChannel();
        const int wheelPos = m.getPitchWheelValue();
        lastPitchWheelValues [channel - 1] = wheelPos;

        handlePitchWheel (channel, wheelPos);
    }
    else if (m.isController())
    {
        handleController (m.getChannel(),
                          m.getControllerNumber(),
                          m.getControllerValue());
    }
}
Esempio n. 2
0
void ISynth::sysexSoundFont(SfOp op, const char* data)
      {
      char c = 'x';
      allNotesOff();
      switch(op) {
            case SF_REMOVE:
                  break;
            case SF_REPLACE:
            case SF_ADD:
                  if (sfont && (strcmp(sfont, data) == 0)) {
                        #ifdef FS_DEBUG
                        fprintf(stderr, "fluid: font already loaded\n");
                        #endif
                        break;
                        }
                  if (_busy) {
                        //#ifdef FS_DEBUG
                        fprintf(stderr, "fluid: busy!\n");
                        //#endif
                        break;
                        }
                  _busy = true;
                  if (sfont)
                        delete[] sfont;
                  sfont = new char[strlen(data)+1];
                  strcpy(sfont, data);
                  _busy = true;
                  write(writeFd, &c, 1);
                  break;
            }
      }
Esempio n. 3
0
bool MidiParser::setTrack(int track) {
	if (track < 0 || track >= _num_tracks)
		return false;
	// We allow restarting the track via setTrack when
	// it isn't playing anymore. This allows us to reuse
	// a MidiParser when a track has finished and will
	// be restarted via setTrack by the client again.
	// This isn't exactly how setTrack behaved before though,
	// the old MidiParser code did not allow setTrack to be
	// used to restart a track, which was already finished.
	//
	// TODO: Check if any engine has problem with this
	// handling, if so we need to find a better way to handle
	// track restarts. (KYRA relies on this working)
	else if (track == _active_track && isPlaying())
		return true;

	if (_smartJump)
		hangAllActiveNotes();
	else
		allNotesOff();

	resetTracking();
	memset(_active_notes, 0, sizeof(_active_notes));
	_active_track = track;
	_position._play_pos = _tracks[track];
	parseNextEvent(_next_event);
	return true;
}
Esempio n. 4
0
void MidiSequencer::stop()
{
    m_midiSequencerOutputThread->stop();
    m_midiSequencerOutputThread->resetPosition();
    emit allNotesOff();
    emit timeLabelChanged("00:00.00");
}
Esempio n. 5
0
//==============================================================================
void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
{
    if (sampleRate != newRate)
    {
        const ScopedLock sl (lock);
        allNotesOff (0, false);
        sampleRate = newRate;

        for (auto* voice : voices)
            voice->setCurrentPlaybackSampleRate (newRate);
    }
}
Esempio n. 6
0
//==============================================================================
void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
{
    if (sampleRate != newRate)
    {
        const ScopedLock sl (lock);

        allNotesOff (0, false);

        sampleRate = newRate;

        for (int i = voices.size(); --i >= 0;)
            voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate);
    }
}
void MidiKeyboardState::allNotesOff (const int midiChannel)
{
    const ScopedLock sl (lock);

    if (midiChannel <= 0)
    {
        for (int i = 1; i <= 16; ++i)
            allNotesOff (i);
    }
    else
    {
        for (int i = 0; i < 128; ++i)
            noteOff (midiChannel, i, 0.0f);
    }
}
Esempio n. 8
0
    void PlayerHandler::process(const jack_nframes_t nframes)
    {
      void* outPortBuf = jack_port_get_buffer(m_outputPort, nframes);

      jack_midi_clear_buffer(outPortBuf);

      jack_position_t pos;
      const jack_transport_state_t state = jack_transport_query(m_client, &pos);

      switch (state)
      {
      case JackTransportStopped:
	{
	  if (m_previousState != state)
	  {
	    // stop them all now
	    allNotesOff(outPortBuf, 0);
	    // reset position
	    m_position = 0;
	  }
	  break;
	}
      case JackTransportRolling:
	{
	  const jack_nframes_t framesAtStart = jack_last_frame_time(m_client);
	  const jack_nframes_t lastFrame = framesAtStart + nframes;

	  const jack_nframes_t startFrame = framesAtStart - pos.frame;

	  while (m_position < m_master.size() && startFrame + m_master[m_position].m_time >= framesAtStart && startFrame + m_master[m_position].m_time < lastFrame)
	  {
	    const MidiEvent & event = m_master[m_position];
	    const jack_nframes_t newOffset = event.m_time - pos.frame;
	    jack_midi_event_write(outPortBuf, newOffset, event.m_data, event.m_size);
	    noteChange(event.m_data);

	    ++m_position;
	  }
	  break;
	}
      default:
	{
	  break;
	}
      }

      m_previousState = state;
    }
Esempio n. 9
0
void MidiParser::unloadMusic() {
	resetTracking();
	allNotesOff();
	_num_tracks = 0;
	_active_track = 255;
	_abort_parse = true;

	if (_centerPitchWheelOnUnload) {
		// Center the pitch wheels in preparation for the next piece of
		// music. It's not safe to do this from within allNotesOff(),
		// and might not even be safe here, so we only do it if the
		// client has explicitly asked for it.

		if (_driver) {
			for (int i = 0; i < 16; ++i) {
				sendToDriver(0xE0 | i, 0, 0x40);
			}
		}
	}
}
Esempio n. 10
0
void MidiInputController::setModePolyphonic(int maxPolyphony) {
    // First turn off any notes in the current mode
    allNotesOff();
    removeAllOscListeners();

    // Register a callback for touchkey data.  When we get a note-on message,
    // we request this callback occur once touch data is available.  In this mode,
    // we know the eventual channel before any touch data ever occurs: thus, we
    // only listen to the MIDI onset itself, which happens after all the touch
    // data is sent out.
    addOscListener("/midi/noteon");

    mode_ = ModePolyphonic;

    retransmitMaxPolyphony_ = maxPolyphony;
    if(retransmitMaxPolyphony_ > 16)
        retransmitMaxPolyphony_ = 16;	// Limit polyphony to 16 (number of MIDI channels
    for(int i = 0; i < retransmitMaxPolyphony_; i++)
        retransmitChannelsAvailable_.insert(i);
    retransmitChannelForNote_.clear();
}
Esempio n. 11
0
void Synthesiser::handleMidiEvent (const MidiMessage& m)
{
    const int channel = m.getChannel();

    if (m.isNoteOn())
    {
        noteOn (channel, m.getNoteNumber(), m.getFloatVelocity());
    }
    else if (m.isNoteOff())
    {
        noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true);
    }
    else if (m.isAllNotesOff() || m.isAllSoundOff())
    {
        allNotesOff (channel, true);
    }
    else if (m.isPitchWheel())
    {
        const int wheelPos = m.getPitchWheelValue();
        lastPitchWheelValues [channel - 1] = wheelPos;
        handlePitchWheel (channel, wheelPos);
    }
    else if (m.isAftertouch())
    {
        handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue());
    }
    else if (m.isChannelPressure())
    {
        handleChannelPressure (channel, m.getChannelPressureValue());
    }
    else if (m.isController())
    {
        handleController (channel, m.getControllerNumber(), m.getControllerValue());
    }
    else if (m.isProgramChange())
    {
        handleProgramChange (channel, m.getProgramChangeNumber());
    }
}
Esempio n. 12
0
void MidiInputController::setModeChannelSelect(int switchType, int numDivisions, int defaultChannel) {
    // First turn off any notes in the current mode
    allNotesOff();
    removeAllOscListeners();

    // Register a callback for touchkey data.  When we get a note-on message,
    // we request this callback occur once touch data is available.  In this mode, we
    // need to know about the touch before we can decide the channel, so we listen to both
    // pre-onset and onset messages
    addOscListener("/touchkeys/preonset");
    addOscListener("/midi/noteon");

    mode_ = ModeChannelSelect;
    channelSelectSwitchType_ = switchType;
    channelSelectNumberOfDivisions_ = numDivisions;
    channelSelectDefaultChannel_ = defaultChannel;

    if(channelSelectNumberOfDivisions_ < 1)
        channelSelectNumberOfDivisions_ = 1;
    if(channelSelectDefaultChannel_ >= channelSelectNumberOfDivisions_)
        channelSelectDefaultChannel_ = channelSelectNumberOfDivisions_ - 1;
    retransmitChannelForNote_.clear();
    channelSelectLastOnsetChannel_ = 0;
}
Esempio n. 13
0
void MidiInputController::setModePassThrough() {
    allNotesOff();
    removeAllOscListeners();
    mode_ = ModePassThrough;
}
Esempio n. 14
0
bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool dontSendNoteOn) {
	if (_active_track >= _num_tracks)
		return false;

	Tracker currentPos(_position);
	EventInfo currentEvent(_next_event);

	resetTracking();
	_position._play_pos = _tracks[_active_track];
	parseNextEvent(_next_event);
	if (tick > 0) {
		while (true) {
			EventInfo &info = _next_event;
			if (_position._last_event_tick + info.delta >= tick) {
				_position._play_time += (tick - _position._last_event_tick) * _psec_per_tick;
				_position._play_tick = tick;
				break;
			}

			_position._last_event_tick += info.delta;
			_position._last_event_time += info.delta * _psec_per_tick;
			_position._play_tick = _position._last_event_tick;
			_position._play_time = _position._last_event_time;

			if (info.event == 0xFF) {
				if (info.ext.type == 0x2F) { // End of track
					_position = currentPos;
					_next_event = currentEvent;
					return false;
				} else {
					if (info.ext.type == 0x51 && info.length >= 3) // Tempo
						setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
					if (fireEvents)
						_driver->metaEvent(info.ext.type, info.ext.data, (uint16) info.length);
				}
			} else if (fireEvents) {
				if (info.event == 0xF0) {
					if (info.ext.data[info.length-1] == 0xF7)
						_driver->sysEx(info.ext.data, (uint16)info.length-1);
					else
						_driver->sysEx(info.ext.data, (uint16)info.length);
				} else {
					// The note on sending code is used by the SCUMM engine. Other engine using this code
					// (such as SCI) have issues with this, as all the notes sent can be heard when a song
					// is fast-forwarded.	Thus, if the engine requests it, don't send note on events.
					if (info.command() == 0x9 && dontSendNoteOn) {
						// Don't send note on; doing so creates a "warble" with some instruments on the MT-32.
						// Refer to patch #3117577
					} else {
						sendToDriver(info.event, info.basic.param1, info.basic.param2);
					}
				}
			}

			parseNextEvent(_next_event);
		}
	}

	if (stopNotes) {
		if (!_smartJump || !currentPos._play_pos) {
			allNotesOff();
		} else {
			EventInfo targetEvent(_next_event);
			Tracker targetPosition(_position);

			_position = currentPos;
			_next_event = currentEvent;
			hangAllActiveNotes();

			_next_event = targetEvent;
			_position = targetPosition;
		}
	}

	_abort_parse = true;
	return true;
}
Esempio n. 15
0
void MidiParser::stopPlaying() {
	allNotesOff();
	resetTracking();
}
Esempio n. 16
0
int OscController::handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *data)
{
	bool matched = false;
	
#ifdef DEBUG_MESSAGES_EXTRA
	cout << "Received OSC message " << path << " [" << types << "]\n";
#endif
	
	if(useOscMidi_)	// OSC MIDI emulation.  Also the most time-sensitive & frequent message so do this first.
	{
		if(!strcmp(path, "/mrp/midi") && argc >= 1)
		{
			if(types[0] == 'm')
				return handleMidi(argv[0]->m[1], argv[0]->m[2], argv[0]->m[3]);
			if(argc >= 3)
				if(types[0] == 'i' && types[1] == 'i' && types[2] == 'i')
					return handleMidi((unsigned char)argv[0]->i, (unsigned char)argv[1]->i, (unsigned char)argv[2]->i);
		}
		if(!strcmp(path, "/mrp/quality/brightness") && argc >= 3)
		{
			if(types[0] == 'i' && types[1] == 'i' && types[2] == 'f')
				return handleRtBrightness(argv);
		}
		if(!strcmp(path, "/mrp/quality/intensity") && argc >= 3)
		{
			if(types[0] == 'i' && types[1] == 'i' && types[2] == 'f')
				return handleRtIntensity(argv);
		}
		if(!strcmp(path, "/mrp/quality/pitch") && argc >= 3)
		{
			if(types[0] == 'i' && types[1] == 'i' && types[2] == 'f')
				return handleRtPitch(argv);
		}
        if(!strcmp(path, "/mrp/quality/pitch/vibrato") && argc >= 3)
		{
			if(types[0] == 'i' && types[1] == 'i' && types[2] == 'f')
				return handleRtPitchVibrato(argv);
		}
		if(!strcmp(path, "/mrp/quality/harmonic") && argc >= 3)
		{
			if(types[0] == 'i' && types[1] == 'i' && types[2] == 'f')
				return handleRtHarmonic(argv);
		}
        if(!strcmp(path, "/mrp/quality/harmonics/raw") && argc >= 3)
		{
			if(types[0] == 'i' && types[1] == 'i' && types[2] == 'f')
				return handleRtHarmonicsRaw(argc, types, argv);
		}
        if(!strcmp(path, "/mrp/volume") && argc >= 1)
		{
			if(types[0] == 'f')
            {
                cout << "setting volume to " << argv[0]->f << endl;
                midiController_->render_->setGlobalAmplitude(argv[0]->f);
				return 0;
            }
		}
        if(!strcmp(path, "/mrp/global/harmonics") && argc == 2)
		{
			if(types[0] == 'i' || types[1] == 'f')
				midiController_->oscHandleGlobalParameters(path, types, 2, argv, data);
		}
        if(!strcmp(path, "/mrp/allnotesoff"))
		{
            allNotesOff();
		}
	}

	string pathString(path);	
	
	if(useThru_)
	{
		// Rebroadcast any matching messages
		
		if(!pathString.compare(0, thruPrefix_.length(), thruPrefix_))
			lo_send_message(thruAddress_, path, msg);
	}
	
	// Check if the incoming message matches the global prefix for this program.  If not, discard it.
	if(pathString.compare(0, globalPrefix_.length(), globalPrefix_))
	{
		cout << "OSC message '" << path << "' received\n";
		return 1;
	}
	
	// Lock the mutex so the list of listeners doesn't change midway through
	pthread_mutex_lock(&oscListenerMutex_);
	
	// Now remove the global prefix and compare the rest of the message to the registered handlers.
	multimap<string, OscHandler*>::iterator it;
	pair<multimap<string, OscHandler*>::iterator,multimap<string, OscHandler*>::iterator> ret;
	string truncatedPath = pathString.substr(globalPrefix_.length(), 
											 pathString.length() - globalPrefix_.length());
	ret = noteListeners_.equal_range(truncatedPath);
	
	it = ret.first;
	while(it != ret.second)
	{
		OscHandler *object = (*it++).second;
		
#ifdef DEBUG_MESSAGES_EXTRA
		cout << "Matched OSC path '" << path << "' to handler " << object << endl;
#endif
		object->oscHandlerMethod(truncatedPath.c_str(), types, argc, argv, data);
		matched = true;
	}
	
	pthread_mutex_unlock(&oscListenerMutex_);
	
	if(matched)		// This message has been handled
		return 0;
	
	printf("Unhandled OSC path: <%s>\n", path);
/*#ifdef DEBUG_MESSAGES
	for (i=0; i<argc; i++) {
		printf("arg %d '%c' ", i, types[i]);
		lo_arg_pp((lo_type)types[i], argv[i]);
		printf("\n");
	}
#endif*/

    return 1;
}
Esempio n. 17
0
bool MidiParser::jumpToTick(uint32 tick, bool fireEvents) {
	if (_active_track >= _num_tracks)
		return false;

	Tracker currentPos(_position);
	EventInfo currentEvent(_next_event);

	resetTracking();
	_position._play_pos = _tracks[_active_track];
	parseNextEvent(_next_event);
	if (tick > 0) {
		while (true) {
			EventInfo &info = _next_event;
			if (_position._last_event_tick + info.delta >= tick) {
				_position._play_time += (tick - _position._last_event_tick) * _psec_per_tick;
				_position._play_tick = tick;
				break;
			}

			_position._last_event_tick += info.delta;
			_position._last_event_time += info.delta * _psec_per_tick;
			_position._play_tick = _position._last_event_tick;
			_position._play_time = _position._last_event_time;

			if (info.event == 0xFF) {
				if (info.ext.type == 0x2F) { // End of track
					_position = currentPos;
					_next_event = currentEvent;
					return false;
				} else {
					if (info.ext.type == 0x51 && info.length >= 3) // Tempo
						setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
					if (fireEvents)
						_driver->metaEvent(info.ext.type, info.ext.data, (uint16) info.length);
				}
			} else if (fireEvents) {
				if (info.event == 0xF0) {
					if (info.ext.data[info.length-1] == 0xF7)
						_driver->sysEx(info.ext.data, (uint16)info.length-1);
					else
						_driver->sysEx(info.ext.data, (uint16)info.length);
				} else
					_driver->send(info.event, info.basic.param1, info.basic.param2);
			}

			parseNextEvent(_next_event);
		}
	}

	if (!_smartJump || !currentPos._play_pos) {
		allNotesOff();
	} else {
		EventInfo targetEvent(_next_event);
		Tracker targetPosition(_position);

		_position = currentPos;
		_next_event = currentEvent;
		hangAllActiveNotes();

		_next_event = targetEvent;
		_position = targetPosition;
	}

	_abort_parse = true;
	return true;
}
Esempio n. 18
0
void MidiInputController::setModeOff() {
    allNotesOff();
    removeAllOscListeners();
    mode_ = ModeOff;
}
Esempio n. 19
0
void MidiSequencer::setPitchShift(unsigned int value)
{
    m_midiSequencerOutputThread->setPitchShift(value);
    emit allNotesOff();
    emit pitchChanged(value);
}
Esempio n. 20
0
void MidiParser_SH::parseNextEvent(EventInfo &info) {
	Common::StackLock lock(_mutex);

//	warning("parseNextEvent");

	// there is no delta right at the start of the music data
	// this order is essential, otherwise notes will get delayed or even go missing
	if (_position._playPos != _tracks[0]) {
		info.delta = *(_position._playPos++);
	} else {
		info.delta = 0;
	}

	info.start = _position._playPos;

	info.event = *_position._playPos++;
	//warning("Event %x", info.event);
	_position._runningStatus = info.event;

	switch (info.command()) {
	case 0xC: { // program change
		int idx = *_position._playPos++;
		info.basic.param1 = idx & 0x7f;
		info.basic.param2 = 0;
		}
		break;
	case 0xD:
		info.basic.param1 = *_position._playPos++;
		info.basic.param2 = 0;
		break;

	case 0xB:
		info.basic.param1 = *_position._playPos++;
		info.basic.param2 = *_position._playPos++;
		info.length = 0;
		break;

	case 0x8:
	case 0x9:
	case 0xA:
	case 0xE:
		info.basic.param1 = *(_position._playPos++);
		info.basic.param2 = *(_position._playPos++);
		if (info.command() == 0x9 && info.basic.param2 == 0) {
			// NoteOn with param2==0 is a NoteOff
			info.event = info.channel() | 0x80;
		}
		info.length = 0;
		break;
	case 0xF:
		if (info.event == 0xFF) {
			error("SysEx META event 0xFF");

			byte type = *(_position._playPos++);
			switch(type) {
			case 0x2F:
				// End of Track
				allNotesOff();
				stopPlaying();
				unloadMusic();
				return;
			case 0x51:
				warning("TODO: 0xFF / 0x51");
				return;
			default:
				warning("TODO: 0xFF / %x Unknown", type);
				break;
			}
		} else if (info.event == 0xFC) {
			// Official End-Of-Track signal
			debugC(kDebugLevelMusic, "Music: System META event 0xFC");

			byte type = *(_position._playPos++);
			switch (type) {
			case 0x80: // end of track, triggers looping
				debugC(kDebugLevelMusic, "Music: META event triggered looping");
				jumpToTick(0, true, true, false);
				break;
			case 0x81: // end of track, stop playing
				debugC(kDebugLevelMusic, "Music: META event triggered music stop");
				stopPlaying();
				unloadMusic();
				break;
			default:
				error("MidiParser_SH::parseNextEvent: Unknown META event 0xFC type %x", type);
				break;
			}
		} else {
			warning("TODO: %x / Unknown", info.event);
			break;
		}
		break;
	default:
		warning("MidiParser_SH::parseNextEvent: Unsupported event code %x", info.event);
		break;
	}// switch (info.command())
}
Esempio n. 21
0
void VPiano::slotPanic()
{
    allNotesOff();
}
Esempio n. 22
0
void Zerberus::allSoundsOff(int channel)
      {
      allNotesOff(channel);
      }
Esempio n. 23
0
void ISynth::gmOn(bool flag)
      {
      _gmMode = flag;
      allNotesOff();
      }