Example #1
0
void
decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf)
{
    int i;
    jack_midi_clear_buffer (buf);
    for (i = 0; i < buffer_size_uint32 - 3;)
    {
        uint32_t payload_size;
        payload_size = buffer_uint32[i];
        payload_size = ntohl (payload_size);
        if (payload_size)
        {
            jack_midi_event_t event;
            event.time = ntohl (buffer_uint32[i+1]);
            event.size = ntohl (buffer_uint32[i+2]);
            event.buffer = (jack_midi_data_t*) (&(buffer_uint32[i+3]));
            jack_midi_event_write (buf, event.time, event.buffer, event.size);

            // skip to the next event
            unsigned int nb_data_quads = (((event.size-1) & ~0x3) >> 2)+1;
            i += 3+nb_data_quads;
        }
        else
            break; // no events can follow an empty event, we're done
    }
Example #2
0
bool MidiBuffer::writeEvent(int sample, MidiData *midiData, size_t dataSize) {
    if(!isValid()) {
        return false;
    }

    return (jack_midi_event_write(
        _jackBuffer,
        (jack_nframes_t)sample,
        (const jack_midi_data_t *)midiData,
        dataSize) == 0);
}
Example #3
0
static
void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct process_info* info)
{
	jack_midi_data_t data[MAX_EVENT_SIZE];
	stream_t *str = &self->stream[PORT_INPUT];
	long size;
	int64_t alsa_time, time_offset;
	int64_t frame_offset, event_frame;
	port_t *port;

	port = port_get(str->ports, alsa_event->source);
	if (!port)
		return;

	/*
	 * RPNs, NRPNs, Bank Change, etc. need special handling
	 * but seems, ALSA does it for us already.
	 */
	snd_midi_event_reset_decode(str->codec);
	if ((size = snd_midi_event_decode(str->codec, data, sizeof(data), alsa_event))<0)
		return;

	// fixup NoteOn with vel 0
	if ((data[0] & 0xF0) == 0x90 && data[2] == 0x00) {
		data[0] = 0x80 + (data[0] & 0x0F);
		data[2] = 0x40;
	}

	alsa_time = alsa_event->time.time.tv_sec * NSEC_PER_SEC + alsa_event->time.time.tv_nsec;
	time_offset = info->alsa_time - alsa_time;
	frame_offset = (info->sample_rate * time_offset) / NSEC_PER_SEC;
	event_frame = (int64_t)info->cur_frames - info->period_start - frame_offset + info->nframes;

	debug_log("input: %d bytes at event_frame = %d", (int)size, (int)event_frame);

	if (event_frame >= info->nframes &&
	    jack_ringbuffer_write_space(port->early_events) >= (sizeof(alsa_midi_event_t) + size)) {
		alsa_midi_event_t ev;
		ev.time = event_frame + info->period_start;
		ev.size = size;
		jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev));
		jack_ringbuffer_write(port->early_events, (char*)data, size);
		debug_log("postponed to next frame +%d", (int) (event_frame - info->nframes));
		return;
	}

	if (event_frame < 0)
		event_frame = 0;
	else if (event_frame >= info->nframes)
		event_frame = info->nframes - 1;

	jack_midi_event_write(port->jack_buf, event_frame, data, size);
}
Example #4
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;
    }
int process(jack_nframes_t nframes, void *arg) {
    int j;
    data *par = (data *) arg;

    jack_midi_event_t *event = (jack_midi_event_t *) jack_port_get_buffer(par->inPort, nframes);
    int eCount = jack_midi_get_event_count(event);
    void *buffer = jack_port_get_buffer(par->outPort, nframes);
    jack_midi_clear_buffer(buffer);

    for (eCount, j = 0; eCount > 0; eCount--, j++) {
        jack_midi_event_t nextE;
        jack_midi_event_get(&nextE, event, j);

        // Filtering by channel
        char ch = nextE.buffer[0] & 0x0F;

        if (par->channelFilter >= 0) {
            if (ch != par->channelFilter) return 0;
        }

        if (nextE.buffer[0] & 0x80 || nextE.buffer[0] & 0x90) {
            if (nextE.buffer[1] >= par->currentNote) {
                nextE.buffer[0] &= 0xF0;
                nextE.buffer[0] += par->ch2Num;
                nextE.buffer[1] += par->ch2Shift;
            }
            else {
                nextE.buffer[0] &= 0xF0;
                nextE.buffer[0] += par->ch1Num;
                nextE.buffer[1] += par->ch1Shift;
            }

        }


        jack_midi_event_write(buffer, nextE.time, nextE.buffer, nextE.size);
    }

    return 0;
}
Example #6
0
int process(jack_nframes_t nframes, void* arg)
{
    TimerProcess.Start();

    static uint64_t frametime = 0;
    TJackSynth* synth = static_cast<TJackSynth*>(arg);

    /* Process MIDI input */
    void* inbuf = jack_port_get_buffer(MidiIn, nframes);
    jack_nframes_t event_count = jack_midi_get_event_count(inbuf);
    for (jack_nframes_t i = 0; i < event_count; i++) {
        jack_midi_event_t event;
        jack_midi_event_get(&event, inbuf, i);
        std::vector<uint8_t> data(event.buffer, event.buffer + event.size);
        synth->HandleMidi(data, frametime + event.time);
    }

    /* Send MIDI */
    void* outbuf = jack_port_get_buffer(MidiOut, nframes);
    jack_midi_clear_buffer(outbuf);
    while (!MidiOutQueue.empty()) {
        const std::vector<uint8_t>& data = MidiOutQueue.front();
        int ret = jack_midi_event_write(outbuf, 0, data.data(), data.size());
        MidiOutQueue.pop();
        if (ret != 0) {
            fprintf(stderr, "MIDI send error\n");
        }
    }

    synth->Process(nframes);

    frametime += nframes;
    TimerProcess.Stop();

    return 0;
}
Example #7
0
void midiSendLong(unsigned char *buf, unsigned long len) {
  /*int err = snd_rawmidi_write(handle_out, buf, len);
  if (err != len) {
    fprintf(stderr, "could not write %ld byte to output, return: %d\n", len, err);
    exit(1);
  }*/
  if (jack_midi_output_port == NULL) {
    fprintf(stderr, "midiSendLong failed: output port closed\n");
    exit(1);
  }

  void* output_buf = jack_port_get_buffer (jack_midi_output_port, 1);   
  jack_midi_clear_buffer(output_buf);  

  printhex("send:", buf, len);

  int err = jack_midi_event_write(output_buf, 0, buf, len);
  if (err != 0) { 
    if (err == ENOBUFS) { // if there's not enough space in buffer for event
    }
    fprintf(stderr, "could not write %ld byte to output, return: %d\n", len, err);
    exit(1);
  }
}
Example #8
0
static int process_cb(jack_nframes_t nframes, void *arg)
{
    struct cbox_jack_io_impl *jii = arg;
    struct cbox_io *io = jii->ioi.pio;
    struct cbox_io_callbacks *cb = io->cb;
    
    io->io_env.buffer_size = nframes;
    for (int i = 0; i < io->io_env.input_count; i++)
        io->input_buffers[i] = jack_port_get_buffer(jii->inputs[i], nframes);
    for (int i = 0; i < io->io_env.output_count; i++)
    {
        io->output_buffers[i] = jack_port_get_buffer(jii->outputs[i], nframes);
        if (!io->output_buffers[i])
            continue;
        for (int j = 0; j < nframes; j ++)
            io->output_buffers[i][j] = 0.f;
    }
    for (GSList *p = io->midi_inputs; p; p = p->next)
    {
        struct cbox_jack_midi_input *input = p->data;
        if (input->hdr.output_set || input->hdr.enable_appsink)
        {
            copy_midi_data_to_buffer(input->port, io->io_env.buffer_size, &input->hdr.buffer);
            if (input->hdr.enable_appsink)
                cbox_midi_appsink_supply(&input->hdr.appsink, &input->hdr.buffer);
        }
        else
            cbox_midi_buffer_clear(&input->hdr.buffer);
    }
    if (cb->on_transport_sync)
    {
        jack_transport_state_t state = jack_transport_query(jii->client, NULL);
        if (state != jii->last_transport_state)
        {
            jack_position_t pos;
            jack_transport_query(jii->client, &pos);
            if (jii->debug_transport)
                g_message("JACK transport: incoming state change, state = %s, last state = %s, pos = %d\n", transport_state_names[state], transport_state_names[(int)jii->last_transport_state], (int)pos.frame);
            if (state == JackTransportStopped)
            {
                if (cb->on_transport_sync(cb->user_data, ts_stopping, pos.frame))
                    jii->last_transport_state = state;
            }
            else
            if (state == JackTransportRolling && jii->last_transport_state == JackTransportStarting)
            {
                if (cb->on_transport_sync(cb->user_data, ts_rolling, pos.frame))
                    jii->last_transport_state = state;
            }
            else
                jii->last_transport_state = state;
        }
    }
    cb->process(cb->user_data, io, nframes);
    for (int i = 0; i < io->io_env.input_count; i++)
        io->input_buffers[i] = NULL;
    for (int i = 0; i < io->io_env.output_count; i++)
        io->output_buffers[i] = NULL;
    for (GSList *p = io->midi_outputs; p; p = g_slist_next(p))
    {
        struct cbox_jack_midi_output *midiout = p->data;

        void *pbuf = jack_port_get_buffer(midiout->port, nframes);
        jack_midi_clear_buffer(pbuf);

        cbox_midi_merger_render(&midiout->hdr.merger);
        if (midiout->hdr.buffer.count)
        {
            uint8_t tmp_data[4];
            for (int i = 0; i < midiout->hdr.buffer.count; i++)
            {
                const struct cbox_midi_event *event = cbox_midi_buffer_get_event(&midiout->hdr.buffer, i);
                const uint8_t *pdata = cbox_midi_event_get_data(event);
                if ((pdata[0] & 0xF0) == 0x90 && !pdata[2] && event->size == 3)
                {
                    tmp_data[0] = pdata[0] & ~0x10;
                    tmp_data[1] = pdata[1];
                    tmp_data[2] = pdata[2];
                    pdata = tmp_data;
                }
                if (jack_midi_event_write(pbuf, event->time, pdata, event->size))
                {
                    g_warning("MIDI buffer overflow on JACK output port '%s'", midiout->hdr.name);
                    break;
                }
            }
        }
    }
    return 0;
}
Example #9
0
// rt
static int
_process(jack_nframes_t nsamples, void *data)
{
	prog_t *handle = data;
	bin_t *bin = &handle->bin;
	sp_app_t *app = bin->app;

#if defined(JACK_HAS_CYCLE_TIMES)
	clock_gettime(CLOCK_REALTIME, &handle->ntp);
	handle->ntp.tv_sec += JAN_1970; // convert NTP to OSC time
	jack_nframes_t offset = jack_frames_since_cycle_start(handle->client);

	float T;
	jack_get_cycle_times(handle->client, &handle->cycle.cur_frames,
		&handle->cycle.cur_usecs, &handle->cycle.nxt_usecs, &T);
	(void)T;
	
	handle->cycle.ref_frames = handle->cycle.cur_frames + offset;

	// calculate apparent period
	double diff = 1e-6 * (handle->cycle.nxt_usecs - handle->cycle.cur_usecs);

	// calculate apparent samples per period
	handle->cycle.dT = nsamples / diff;
	handle->cycle.dTm1 = 1.0 / handle->cycle.dT;
#endif

	// get transport position
	jack_position_t pos;
	jack_transport_state_t rolling = jack_transport_query(handle->client, &pos) == JackTransportRolling;
	int trans_changed = (rolling != handle->trans.rolling)
		|| (pos.frame != handle->trans.frame)
		|| (pos.beats_per_bar != handle->trans.beats_per_bar)
		|| (pos.beat_type != handle->trans.beat_type)
		|| (pos.ticks_per_beat != handle->trans.ticks_per_beat)
		|| (pos.beats_per_minute != handle->trans.beats_per_minute);

	const size_t sample_buf_size = sizeof(float) * nsamples;
	const sp_app_system_source_t *sources = sp_app_get_system_sources(app);
	const sp_app_system_sink_t *sinks = sp_app_get_system_sinks(app);

	if(sp_app_bypassed(app)) // aka loading state
	{
		//fprintf(stderr, "app is bypassed\n");

		// clear output buffers
		for(const sp_app_system_sink_t *sink=sinks;
			sink->type != SYSTEM_PORT_NONE;
			sink++)
		{
			switch(sink->type)
			{
				case SYSTEM_PORT_NONE:
				case SYSTEM_PORT_CONTROL:
				case SYSTEM_PORT_COM:
					break;

				case SYSTEM_PORT_AUDIO:
				case SYSTEM_PORT_CV:
				{
					void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
					memset(out_buf, 0x0, sample_buf_size);
					break;
				}
				case SYSTEM_PORT_MIDI:
				case SYSTEM_PORT_OSC:
				{
					void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
					jack_midi_clear_buffer(out_buf);
					break;
				}
			}
		}

		bin_process_pre(bin, nsamples, true);
		bin_process_post(bin);

		return 0;
	}

	//TODO use __builtin_assume_aligned

	// fill input buffers
	for(const sp_app_system_source_t *source=sources;
		source->type != SYSTEM_PORT_NONE;
		source++)
	{
		switch(source->type)
		{
			case SYSTEM_PORT_NONE:
			case SYSTEM_PORT_CONTROL:
				break;

			case SYSTEM_PORT_AUDIO:
			case SYSTEM_PORT_CV:
			{
				const void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
				memcpy(source->buf, in_buf, sample_buf_size);
				break;
			}
			case SYSTEM_PORT_MIDI:
			{
				void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
				void *seq_in = source->buf;

				LV2_Atom_Forge *forge = &handle->forge;
				LV2_Atom_Forge_Frame frame;
				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);

				if(ref && trans_changed)
					ref = _trans_event(handle, forge, rolling, &pos);

				int n = jack_midi_get_event_count(in_buf);
				for(int i=0; i<n; i++)
				{
					jack_midi_event_t mev;
					jack_midi_event_get(&mev, in_buf, i);

					//add jack midi event to in_buf
					if(ref)
						ref = lv2_atom_forge_frame_time(forge, mev.time);
					if(ref)
						ref = lv2_atom_forge_atom(forge, mev.size, handle->midi_MidiEvent);
					if(ref)
						ref = lv2_atom_forge_raw(forge, mev.buffer, mev.size);
					if(ref)
						lv2_atom_forge_pad(forge, mev.size);
				}
				if(ref)
					lv2_atom_forge_pop(forge, &frame);
				else
					lv2_atom_sequence_clear(seq_in);

				break;
			}

			case SYSTEM_PORT_OSC:
			{
				void *in_buf = jack_port_get_buffer(source->sys_port, nsamples);
				void *seq_in = source->buf;

				LV2_Atom_Forge *forge = &handle->forge;
				LV2_Atom_Forge_Frame frame;
				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);

				if(ref && trans_changed)
					ref = _trans_event(handle, forge, rolling, &pos);

				int n = jack_midi_get_event_count(in_buf);	
				for(int i=0; i<n; i++)
				{
					jack_midi_event_t mev;
					jack_midi_event_get(&mev, (void *)in_buf, i);

					//add jack osc event to in_buf
					if(osc_check_packet(mev.buffer, mev.size))
					{
						if(ref)
							ref = lv2_atom_forge_frame_time(forge, mev.time);
						handle->ref = ref;
						osc_dispatch_method(mev.buffer, mev.size, methods,
							_bundle_in, _bundle_out, handle);
						ref = handle->ref;
					}
				}
				if(ref)
					lv2_atom_forge_pop(forge, &frame);
				else
					lv2_atom_sequence_clear(seq_in);

				break;
			}

			case SYSTEM_PORT_COM:
			{
				void *seq_in = source->buf;

				LV2_Atom_Forge *forge = &handle->forge;
				LV2_Atom_Forge_Frame frame;
				lv2_atom_forge_set_buffer(forge, seq_in, SEQ_SIZE);
				LV2_Atom_Forge_Ref ref = lv2_atom_forge_sequence_head(forge, &frame, 0);

				const LV2_Atom_Object *obj;
				size_t size;
				while((obj = varchunk_read_request(bin->app_from_com, &size)))
				{
					if(ref)
						ref = lv2_atom_forge_frame_time(forge, 0);
					if(ref)
						ref = lv2_atom_forge_raw(forge, obj, size);
					if(ref)
						lv2_atom_forge_pad(forge, size);

					varchunk_read_advance(bin->app_from_com);
				}
				if(ref)
					lv2_atom_forge_pop(forge, &frame);
				else
					lv2_atom_sequence_clear(seq_in);

				break;
			}
		}
	}

	// update transport state
	handle->trans.rolling = rolling;
	handle->trans.frame = rolling
		? handle->trans.frame + nsamples
		: pos.frame;
	handle->trans.beats_per_bar = pos.beats_per_bar;
	handle->trans.beat_type = pos.beat_type;
	handle->trans.ticks_per_beat = pos.ticks_per_beat;
	handle->trans.beats_per_minute = pos.beats_per_minute;

	bin_process_pre(bin, nsamples, false);

	// fill output buffers
	for(const sp_app_system_sink_t *sink=sinks;
		sink->type != SYSTEM_PORT_NONE;
		sink++)
	{
		switch(sink->type)
		{
			case SYSTEM_PORT_NONE:
			case SYSTEM_PORT_CONTROL:
				break;

			case SYSTEM_PORT_AUDIO:
			case SYSTEM_PORT_CV:
			{
				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
				memcpy(out_buf, sink->buf, sample_buf_size);
				break;
			}
			case SYSTEM_PORT_MIDI:
			{
				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
				const LV2_Atom_Sequence *seq_out = sink->buf;

				// fill midi output buffer
				jack_midi_clear_buffer(out_buf);
				if(seq_out)
				{
					LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
					{
						const LV2_Atom *atom = &ev->body;

						if(atom->type != handle->midi_MidiEvent)
							continue; // ignore non-MIDI events

						jack_midi_event_write(out_buf, ev->time.frames,
							LV2_ATOM_BODY_CONST(atom), atom->size);
					}
				}

				break;
			}

			case SYSTEM_PORT_OSC:
			{
				void *out_buf = jack_port_get_buffer(sink->sys_port, nsamples);
				const LV2_Atom_Sequence *seq_out = sink->buf;

				// fill midi output buffer
				jack_midi_clear_buffer(out_buf);
				if(seq_out)
				{
					LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
					{
						const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;

						handle->osc_ptr = handle->osc_buf;
						handle->osc_end = handle->osc_buf + OSC_SIZE;

						osc_atom_event_unroll(&handle->oforge, obj, _bundle_push_cb,
							_bundle_pop_cb, _message_cb, handle);

						size_t size = handle->osc_ptr
							? handle->osc_ptr - handle->osc_buf
							: 0;

						if(size)
						{
							jack_midi_event_write(out_buf, ev->time.frames,
								handle->osc_buf, size);
						}
					}
				}

				break;
			}

			case SYSTEM_PORT_COM:
			{
				const LV2_Atom_Sequence *seq_out = sink->buf;

				LV2_ATOM_SEQUENCE_FOREACH(seq_out, ev)
				{
					const LV2_Atom *atom = (const LV2_Atom *)&ev->body;

					// try do process events directly
					bin->advance_ui = sp_app_from_ui(bin->app, atom);
					if(!bin->advance_ui) // queue event in ringbuffer instead
					{
						//fprintf(stderr, "plugin ui direct is blocked\n");

						void *ptr;
						size_t size = lv2_atom_total_size(atom);
						if((ptr = varchunk_write_request(bin->app_from_app, size)))
						{
							memcpy(ptr, atom, size);
							varchunk_write_advance(bin->app_from_app, size);
						}
						else
						{
							//fprintf(stderr, "app_from_ui ringbuffer full\n");
							//FIXME
						}
					}
				}
				break;
			}
		}
	}
	
	bin_process_post(bin);

	return 0;
}
Example #10
0
    void ModeHandler::process(const jack_nframes_t nframes)
    {
      void* inPortBuf = jack_port_get_buffer(m_inputPort, nframes);
      void* outPortBuf = jack_port_get_buffer(m_outputPort, nframes);

      jack_midi_clear_buffer(outPortBuf);

      const jack_transport_state_t state = jack_transport_query(m_client, nullptr);

      const jack_nframes_t eventCount = jack_midi_get_event_count(inPortBuf);

      for (size_t i = 0; i < eventCount; ++i)
      {
	jack_midi_event_t inEvent;
	jack_midi_event_get(&inEvent, inPortBuf, i);

	const jack_midi_data_t cmd = inEvent.buffer[0] & 0xf0;

	switch (cmd)
	{
	case MIDI_NOTEON:
	case MIDI_NOTEOFF:
	  {
	    const jack_midi_data_t note = inEvent.buffer[1];
	    const jack_midi_data_t velocity = inEvent.buffer[2];

	    int noteToUse = note;

	    // we only map on a note on
	    // on a note off we use the previously mapped note
	    // and only is transport is rolling
	    if (cmd == MIDI_NOTEON && velocity > 0)
	    {
	      if (state == JackTransportRolling)
	      {
		const int newNote = transpose(m_offset, m_quirkOffset, note);

		m_mappedNotes[note] = newNote;
		noteToUse = newNote;
	      }
	    }
	    else
	    {
	      // NOTEOFF
	      if (m_mappedNotes[note] != NOT_MAPPED)
	      {
		noteToUse = m_mappedNotes[note];
		m_mappedNotes[note] = NOT_MAPPED;
	      }
	    }

	    if (noteToUse != SKIP)
	    {
	      jack_midi_data_t data[3];
	      data[0] = inEvent.buffer[0];
	      data[1] = noteToUse;;
	      data[2] = inEvent.buffer[2];

	      jack_midi_event_write(outPortBuf, inEvent.time, data, 3);
	    }
	    break;
	  }
	default:
	  {
	    // just forward everything else
	    jack_midi_event_write(outPortBuf, inEvent.time, inEvent.buffer, inEvent.size);
	  }
	}
      }
    }