/*
 * 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);
	}
}
Exemplo n.º 2
0
/*
 * fluid_midi_file_read_event
 */
int
fluid_midi_file_read_event(fluid_midi_file *mf, fluid_track_t *track, int num)
{
    int status;
    int type;
    int tempo;
    unsigned char *metadata = NULL;
    unsigned char *dyn_buf = NULL;
    unsigned char static_buf[256];
    int nominator, denominator, clocks, notes;
    fluid_midi_event_t *evt;
    int channel = 0;
    int param1 = 0;
    int param2 = 0;
    int size;

    /* read the delta-time of the event */
    if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
        return FLUID_FAILED;
    }
    mf->dtime += mf->varlen;

    /* read the status byte */
    status = fluid_midi_file_getc(mf);
    if (status < 0) {
        FLUID_LOG(FLUID_ERR, "Unexpected end of file");
        return FLUID_FAILED;
    }

    /* not a valid status byte: use the running status instead */
    if ((status & 0x80) == 0) {
        if ((mf->running_status & 0x80) == 0) {
            FLUID_LOG(FLUID_ERR, "Undefined status and invalid running status");
            return FLUID_FAILED;
        }
        fluid_midi_file_push(mf, status);
        status = mf->running_status;
    }

    /* check what message we have */

    mf->running_status = status;

    if ((status == MIDI_SYSEX)) { /* system exclusif */
        /* read the length of the message */
        if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
            return FLUID_FAILED;
        }

        if (mf->varlen) {
            FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
                    __LINE__, mf->varlen);
            metadata = FLUID_MALLOC(mf->varlen + 1);

            if (metadata == NULL) {
                FLUID_LOG(FLUID_PANIC, "Out of memory");
                return FLUID_FAILED;
            }

            /* read the data of the message */
            if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
                FLUID_FREE (metadata);
                return FLUID_FAILED;
            }

            evt = new_fluid_midi_event();
            if (evt == NULL) {
                FLUID_LOG(FLUID_ERR, "Out of memory");
                FLUID_FREE (metadata);
                return FLUID_FAILED;
            }

            evt->dtime = mf->dtime;
            size = mf->varlen;

            if (metadata[mf->varlen - 1] == MIDI_EOX)
                size--;

            /* Add SYSEX event and indicate that its dynamically allocated and should be freed with event */
            fluid_midi_event_set_sysex(evt, metadata, size, TRUE);
            fluid_track_add_event(track, evt);
            mf->dtime = 0;
        }

        return FLUID_OK;

    } else if (status == MIDI_META_EVENT) { /* meta events */

        int result = FLUID_OK;

        /* get the type of the meta message */
        type = fluid_midi_file_getc(mf);
        if (type < 0) {
            FLUID_LOG(FLUID_ERR, "Unexpected end of file");
            return FLUID_FAILED;
        }

        /* get the length of the data part */
        if (fluid_midi_file_read_varlen(mf) != FLUID_OK) {
            return FLUID_FAILED;
        }

        if (mf->varlen < 255) {
            metadata = &static_buf[0];
        } else {
            FLUID_LOG(FLUID_DBG, "%s: %d: alloc metadata, len = %d", __FILE__,
                    __LINE__, mf->varlen);
            dyn_buf = FLUID_MALLOC(mf->varlen + 1);
            if (dyn_buf == NULL) {
                FLUID_LOG(FLUID_PANIC, "Out of memory");
                return FLUID_FAILED;
            }
            metadata = dyn_buf;
        }

        /* read the data */
        if (mf->varlen) {
            if (fluid_midi_file_read(mf, metadata, mf->varlen) != FLUID_OK) {
                if (dyn_buf) {
                    FLUID_FREE(dyn_buf);
                }
                return FLUID_FAILED;
            }
        }

        /* handle meta data */
        switch (type) {

            case MIDI_COPYRIGHT:
                metadata[mf->varlen] = 0;
                break;

            case MIDI_TRACK_NAME:
                metadata[mf->varlen] = 0;
                fluid_track_set_name(track, (char *) metadata);
                break;

            case MIDI_INST_NAME:
                metadata[mf->varlen] = 0;
                break;

            case MIDI_LYRIC:
                break;

            case MIDI_MARKER:
                break;

            case MIDI_CUE_POINT:
                break; /* don't care much for text events */

            case MIDI_EOT:
                if (mf->varlen != 0) {
                    FLUID_LOG(FLUID_ERR, "Invalid length for EndOfTrack event");
                    result = FLUID_FAILED;
                    break;
                }
                mf->eot = 1;
                evt = new_fluid_midi_event();
                if (evt == NULL) {
                    FLUID_LOG(FLUID_ERR, "Out of memory");
                    result = FLUID_FAILED;
                    break;
                }
                evt->dtime = mf->dtime;
                evt->type = MIDI_EOT;
                fluid_track_add_event(track, evt);
                mf->dtime = 0;
                break;

            case MIDI_SET_TEMPO:
                if (mf->varlen != 3) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for SetTempo meta event");
                    result = FLUID_FAILED;
                    break;
                }
                tempo = (metadata[0] << 16) + (metadata[1] << 8) + metadata[2];
                evt = new_fluid_midi_event();
                if (evt == NULL) {
                    FLUID_LOG(FLUID_ERR, "Out of memory");
                    result = FLUID_FAILED;
                    break;
                }
                evt->dtime = mf->dtime;
                evt->type = MIDI_SET_TEMPO;
                evt->channel = 0;
                evt->param1 = tempo;
                evt->param2 = 0;
                fluid_track_add_event(track, evt);
                mf->dtime = 0;
                break;

            case MIDI_SMPTE_OFFSET:
                if (mf->varlen != 5) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for SMPTE Offset meta event");
                    result = FLUID_FAILED;
                    break;
                }
                break; /* we don't use smtp */

            case MIDI_TIME_SIGNATURE:
                if (mf->varlen != 4) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for TimeSignature meta event");
                    result = FLUID_FAILED;
                    break;
                }
                nominator = metadata[0];
                denominator = pow(2.0, (double) metadata[1]);
                clocks = metadata[2];
                notes = metadata[3];

                FLUID_LOG(FLUID_DBG,
                        "signature=%d/%d, metronome=%d, 32nd-notes=%d",
                        nominator, denominator, clocks, notes);

                break;

            case MIDI_KEY_SIGNATURE:
                if (mf->varlen != 2) {
                    FLUID_LOG(FLUID_ERR,
                            "Invalid length for KeySignature meta event");
                    result = FLUID_FAILED;
                    break;
                }
                /* We don't care about key signatures anyway */
                /* sf = metadata[0];
                mi = metadata[1]; */
                break;

            case MIDI_SEQUENCER_EVENT:
                break;

            default:
                break;
        }

        if (dyn_buf) {
            FLUID_LOG(FLUID_DBG, "%s: %d: free metadata", __FILE__, __LINE__);
            FLUID_FREE(dyn_buf);
        }

        return result;

    } else { /* channel messages */

        type = status & 0xf0;
        channel = status & 0x0f;

        /* all channel message have at least 1 byte of associated data */
        if ((param1 = fluid_midi_file_getc(mf)) < 0) {
            FLUID_LOG(FLUID_ERR, "Unexpected end of file");
            return FLUID_FAILED;
        }

        switch (type) {

            case NOTE_ON:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case NOTE_OFF:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case KEY_PRESSURE:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case CONTROL_CHANGE:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }
                break;

            case PROGRAM_CHANGE:
                break;

            case CHANNEL_PRESSURE:
                break;

            case PITCH_BEND:
                if ((param2 = fluid_midi_file_getc(mf)) < 0) {
                    FLUID_LOG(FLUID_ERR, "Unexpected end of file");
                    return FLUID_FAILED;
                }

                param1 = ((param2 & 0x7f) << 7) | (param1 & 0x7f);
                param2 = 0;
                break;

            default:
                /* Can't possibly happen !? */
                FLUID_LOG(FLUID_ERR, "Unrecognized MIDI event");
                return FLUID_FAILED;
        }
        evt = new_fluid_midi_event();
        if (evt == NULL) {
            FLUID_LOG(FLUID_ERR, "Out of memory");
            return FLUID_FAILED;
        }
        evt->dtime = mf->dtime;
        evt->type = type;
        evt->channel = channel;
        evt->param1 = param1;
        evt->param2 = param2;
        evt->track = num;
        fluid_track_add_event(track, evt);
        mf->dtime = 0;
    }
    return FLUID_OK;
}