Пример #1
0
int midi_event_callback(void* data, fluid_midi_event_t* event)
{

	int track_num = (vgmtrans_fluid_midi_event_get_track((vgmtrans_fluid_midi_event_t*)event))->num;
    int chan = fluid_midi_event_get_channel(event);
    int new_chan = ((track_num / 15) * 16) + chan;
    fluid_midi_event_set_channel(event, new_chan);

	return fluid_synth_handle_midi_event(data, event);
}
Пример #2
0
/*
 * fluid_midishare_keyoff_task
 */
static void fluid_midishare_keyoff_task (long date, short ref, long a1, long a2, long a3)
{
    fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref);
    fluid_midi_event_t new_event;
    MidiEvPtr e =(MidiEvPtr)a1;

    fluid_midi_event_set_type(&new_event, NOTE_OFF);
    fluid_midi_event_set_channel(&new_event, Chan(e));
    fluid_midi_event_set_pitch(&new_event, Pitch(e));
    fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */

    /* and send it on its way to the router */
    (*dev->driver.handler)(dev->driver.data, &new_event);

    MidiFreeEv(e);
}
/*
 * Class:     org_tritonus_midi_device_fluidsynth_FluidSynthesizer
 * Method:    nReceive
 * Signature: (IIII)V
 */
JNIEXPORT void JNICALL Java_org_tritonus_midi_device_fluidsynth_FluidSynthesizer_nReceive
(JNIEnv *env, jobject obj, jint command, jint channel, jint data1, jint data2)
{
	fluid_midi_event_t* event;
	fluid_synth_t* synth = get_synth(env, obj);

#ifdef VARIADIC_MACROS
	out("nReceive: synth: %p, values: %x %d %d %d\n", synth, (int) command, (int) channel, (int) data1, (int) data2);
#else
	if (debug_flag)
	{
		fprintf(debug_file, "synth: %p, values: %x %d %d %d\n", synth, (int) command, (int) channel, (int) data1, (int) data2);
		fflush(debug_file);
	}
#endif
	if (synth)
	{
		event = new_fluid_midi_event();
		if (!event)
		{
			printf("failed to instantiate fluid_midi_event_t\n");
			return;
		}
		//printf("2"); fflush(stdout);
		fluid_midi_event_set_type(event, command);
		fluid_midi_event_set_channel(event, channel);
		fluid_midi_event_set_key(event, data1);
		fluid_midi_event_set_velocity(event, data2);
		//printf("3"); fflush(stdout);
		/*printf("values2: %d %d %d %d\n",
		fluid_midi_event_get_type(event),
		fluid_midi_event_get_channel(event),
		fluid_midi_event_get_key(event),
		fluid_midi_event_get_velocity(event));
		fflush(stdout);
	*/
		fluid_synth_handle_midi_event(synth, event);
		//printf("4"); fflush(stdout);
		delete_fluid_midi_event(event);
		//printf("5\n"); fflush(stdout);
	}
}
Пример #4
0
/**
 * Handle a MIDI event through a MIDI router instance.
 * @param data MIDI router instance #fluid_midi_router_t, its a void * so that
 *   this function can be used as a callback for other subsystems
 *   (new_fluid_midi_driver() for example).
 * @param event MIDI event to handle
 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
 *
 * Purpose: The midi router is called for each event, that is received
 * via the 'physical' midi input. Each event can trigger an arbitrary number
 * of generated events (one for each rule that matches).
 *
 * In default mode, a noteon event is just forwarded to the synth's 'noteon' function,
 * a 'CC' event to the synth's 'CC' function and so on.
 *
 * The router can be used to:
 * - filter messages (for example: Pass sustain pedal CCs only to selected channels)
 * - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2)
 * - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
 * - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users
 *   a chance)
 * - velocity switching ("v <=100: Angel Choir; V > 100: Hell's Bells")
 * - get rid of aftertouch
 * - ...
 */
int
fluid_midi_router_handle_midi_event (void* data, fluid_midi_event_t* event)
{
  fluid_midi_router_t* router = (fluid_midi_router_t *)data;
  fluid_midi_router_rule_t **rulep, *rule, *next_rule, *prev_rule = NULL;
  int event_has_par2 = 0; /* Flag, indicates that current event needs two parameters */
  int par1_max = 127;     /* Range limit for par1 */
  int par2_max = 127;     /* Range limit for par2 */
  int ret_val = FLUID_OK;

  int chan; /* Channel of the generated event */
  int par1; /* par1 of the generated event */
  int par2;
  int event_par1;
  int event_par2;
  fluid_midi_event_t new_event;

  /* Some keyboards report noteoff through a noteon event with vel=0.
   * Convert those to noteoff to ease processing. */
  if (event->type == NOTE_ON && event->param2 == 0)
  {
    event->type = NOTE_OFF;
    event->param2 = 127;        /* Release velocity */
  }

  fluid_mutex_lock (router->rules_mutex);   /* ++ lock rules */

  /* Depending on the event type, choose the correct list of rules. */
  switch (event->type)
  {
      case NOTE_ON:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE];
	event_has_par2 = 1;
	break;
      case NOTE_OFF:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE];
	event_has_par2 = 1;
	break;
      case CONTROL_CHANGE:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CC];
	event_has_par2 = 1;
	break;
      case PROGRAM_CHANGE:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PROG_CHANGE];
	break;
      case PITCH_BEND:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PITCH_BEND];
	par1_max = 16383;
	break;
      case CHANNEL_PRESSURE:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE];
	break;
      case KEY_PRESSURE:
	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE];
	event_has_par2 = 1;
	break;
      case MIDI_SYSTEM_RESET:
      case MIDI_SYSEX:
        ret_val = router->event_handler (router->event_handler_data,event);
        fluid_mutex_unlock (router->rules_mutex);  /* -- unlock rules */
        return ret_val;
      default:
        rulep = NULL;    /* Event will not be passed on */
	break;
  }

  /* Loop over rules in the list, looking for matches for this event. */
  for (rule = rulep ? *rulep : NULL; rule; prev_rule = rule, rule = next_rule)
  {
    event_par1 = (int)event->param1;
    event_par2 = (int)event->param2;
    next_rule = rule->next;     /* Rule may get removed from list, so get next here */

    /* Channel window */
    if (rule->chan_min > rule->chan_max)
    { /* Inverted rule: Exclude everything between max and min (but not min/max) */
      if (event->channel > rule->chan_max && event->channel < rule->chan_min)
	continue;
    }
    else        /* Normal rule: Exclude everything < max or > min (but not min/max) */
    {
      if (event->channel > rule->chan_max || event->channel < rule->chan_min)
	continue;
    }

    /* Par 1 window */
    if (rule->par1_min > rule->par1_max)
    { /* Inverted rule: Exclude everything between max and min (but not min/max) */
      if (event_par1 > rule->par1_max && event_par1 < rule->par1_min)
	continue;
    }
    else        /* Normal rule: Exclude everything < max or > min (but not min/max)*/
    {
      if (event_par1 > rule->par1_max || event_par1 < rule->par1_min)
	continue;
    }

    /* Par 2 window (only applies to event types, which have 2 pars)
     * For noteoff events, velocity switching doesn't make any sense.
     * Velocity scaling might be useful, though.
     */
    if (event_has_par2 && event->type != NOTE_OFF)
    {
      if (rule->par2_min > rule->par2_max)
      { /* Inverted rule: Exclude everything between max and min (but not min/max) */
	if (event_par2 > rule->par2_max && event_par2 < rule->par2_min)
	  continue;
      }
      else      /* Normal rule: Exclude everything < max or > min (but not min/max)*/
      {
	if (event_par2 > rule->par2_max || event_par2 < rule->par2_min)
	  continue;
      }
    }

    /* Channel scaling / offset
     * Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all
     * input channels is mapped to the same synth channel.
     */
    chan = (int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul
                 + (fluid_real_t)rule->chan_add + 0.5);

    /* Par 1 scaling / offset */
    par1 = (int)((fluid_real_t)event_par1 * (fluid_real_t)rule->par1_mul
                 + (fluid_real_t)rule->par1_add + 0.5);

    /* Par 2 scaling / offset, if applicable */
    if (event_has_par2)
      par2 = (int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul
                   + (fluid_real_t)rule->par2_add + 0.5);
    else par2 = 0;

    /* Channel range limiting */
    if (chan < 0)
      chan = 0;
    else if (chan >= router->nr_midi_channels)
      chan = router->nr_midi_channels - 1;

    /* Par1 range limiting */
    if (par1 < 0)
      par1 = 0;
    else if (par1 > par1_max)
      par1 = par1_max;

    /* Par2 range limiting */
    if (event_has_par2)
    {
      if (par2 < 0)
        par2 = 0;
      else if (par2 > par2_max)
        par2 = par2_max;
    }

    /* At this point we have to create an event of event->type on 'chan' with par1 (maybe par2).
     * We keep track on the state of noteon and sustain pedal events. If the application tries
     * to delete a rule, it will only be fully removed, if pending noteoff / pedal off events have
     * arrived. In the meantime while waiting, it will only let through 'negative' events
     * (noteoff or pedal up).
     */
    if (event->type == NOTE_ON || (event->type == CONTROL_CHANGE
                                   && par1 == SUSTAIN_SWITCH && par2 >= 64))
    {
      /* Noteon or sustain pedal down event generated */
      if (rule->keys_cc[par1] == 0)
      {
	rule->keys_cc[par1] = 1;
	rule->pending_events++;
      }
    }
    else if (event->type == NOTE_OFF || (event->type == CONTROL_CHANGE
                                         && par1 == SUSTAIN_SWITCH && par2 < 64))
    { /* Noteoff or sustain pedal up event generated */
      if (rule->keys_cc[par1] > 0)
      {
	rule->keys_cc[par1] = 0;
	rule->pending_events--;

        /* Rule is waiting for negative event to be destroyed? */
        if (rule->waiting)
        {
	  if (rule->pending_events == 0)
          { /* Remove rule from rule list */
            if (prev_rule) prev_rule->next = next_rule;
            else *rulep = next_rule;

            /* Add to free list */
            rule->next = router->free_rules;
            router->free_rules = rule;

            rule = prev_rule;   /* Set rule to previous rule, which gets assigned to the next prev_rule value (in for() statement) */
          }

          goto send_event;      /* Pass the event to complete the cycle */
        }
      }
    }

    /* Rule is still waiting for negative event? (note off or pedal up) */
    if (rule->waiting)
      continue;         /* Skip (rule is inactive except for matching negative event) */

send_event:

    /* At this point it is decided, what is sent to the synth.
     * Create a new event and make the appropriate call */

    fluid_midi_event_set_type (&new_event, event->type);
    fluid_midi_event_set_channel (&new_event, chan);
    new_event.param1 = par1;
    new_event.param2 = par2;

    /* FIXME - What should be done on failure?  For now continue to process events, but return failure to caller. */
    if (router->event_handler (router->event_handler_data, &new_event) != FLUID_OK)
      ret_val = FLUID_FAILED;
  }

  fluid_mutex_unlock (router->rules_mutex);         /* -- unlock rules */

  return ret_val;
}
Пример #5
0
/*
 * fluid_midishare_midi_driver_receive
 */
static void fluid_midishare_midi_driver_receive(short ref)
{
    fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref);
    fluid_midi_event_t new_event;
    MidiEvPtr e;
    int count, i;

    while ((e = MidiGetEv (ref)))
    {
        switch (EvType (e))
        {
        case typeNote:
            /* Copy the data to fluid_midi_event_t */
            fluid_midi_event_set_type(&new_event, NOTE_ON);
            fluid_midi_event_set_channel(&new_event, Chan(e));
            fluid_midi_event_set_pitch(&new_event, Pitch(e));
            fluid_midi_event_set_velocity(&new_event, Vel(e));

            /* and send it on its way to the router */
            (*dev->driver.handler)(dev->driver.data, &new_event);

#if defined(MACINTOSH) && defined(MACOS9)
            MidiTask(dev->upp_task_ptr, MidiGetTime()+Dur(e), ref, (long)e, 0, 0);
#else
            MidiTask(fluid_midishare_keyoff_task, MidiGetTime()+Dur(e), ref, (long)e, 0, 0);
#endif

            /* e gets freed in fluid_midishare_keyoff_task */
            continue;

        case typeKeyOn:
            /* Copy the data to fluid_midi_event_t */
            fluid_midi_event_set_type(&new_event, NOTE_ON);
            fluid_midi_event_set_channel(&new_event, Chan(e));
            fluid_midi_event_set_pitch(&new_event, Pitch(e));
            fluid_midi_event_set_velocity(&new_event, Vel(e));
            break;

        case typeKeyOff:
            /* Copy the data to fluid_midi_event_t */
            fluid_midi_event_set_type(&new_event, NOTE_OFF);
            fluid_midi_event_set_channel(&new_event, Chan(e));
            fluid_midi_event_set_pitch(&new_event, Pitch(e));
            fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */
            break;

        case typeCtrlChange:
            /* Copy the data to fluid_midi_event_t */
            fluid_midi_event_set_type(&new_event, CONTROL_CHANGE);
            fluid_midi_event_set_channel(&new_event, Chan(e));
            fluid_midi_event_set_control(&new_event, MidiGetField(e,0));
            fluid_midi_event_set_value(&new_event, MidiGetField(e,1));
            break;

        case typeProgChange:
            /* Copy the data to fluid_midi_event_t */
            fluid_midi_event_set_type(&new_event, PROGRAM_CHANGE);
            fluid_midi_event_set_channel(&new_event, Chan(e));
            fluid_midi_event_set_program(&new_event, MidiGetField(e,0));
            break;

        case typePitchWheel:
            /* Copy the data to fluid_midi_event_t */
            fluid_midi_event_set_type(&new_event, PITCH_BEND);
            fluid_midi_event_set_channel(&new_event, Chan(e));
            fluid_midi_event_set_value(&new_event, ((MidiGetField(e,0)
                                                    + (MidiGetField(e,1) << 7))
                                                    - 8192));
            break;

        case typeSysEx:
            count = MidiCountFields (e);

            /* Discard empty or too large SYSEX messages */
            if (count == 0 || count > FLUID_MIDI_PARSER_MAX_DATA_SIZE)
            {
                MidiFreeEv (e);
                continue;
            }

            /* Copy SYSEX data, one byte at a time */
            for (i = 0; i < count; i++)
                dev->sysexbuf[i] = MidiGetField (e, i);

            fluid_midi_event_set_sysex (&new_event, dev->sysexbuf, count, FALSE);
            break;

        default:
            MidiFreeEv (e);
            continue;
        }

        MidiFreeEv (e);

        /* Send the MIDI event */
        (*dev->driver.handler)(dev->driver.data, &new_event);
    }
}