/* * 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); } }
/* * 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; }