Importing the fluidsynth_jni and fluidmax projects

This commit is contained in:
Peter Hanappe 2004-03-26 14:58:51 +00:00
parent e541eb9d28
commit 67e7a5cbad
24 changed files with 2374 additions and 0 deletions

View file

@ -0,0 +1,11 @@
This directory contains the projects that bind FluidSynth to a
language or host application. The following projects are currently
available:
fluidmax: Provides the fluidsynth~ external object for
Max/MSP. Written by Norbert Schnell.
fluidsynth_jni: Provides a native interface for the Java
language. Written by Peter Hanappe.

View file

@ -0,0 +1,47 @@
Well, this is fluidsynth~ for Max/MSP...
Take a look here:
http://www.ircam.fr/equipes/temps-reel/maxmsp/fluidsynth.html
In order to build the fluidmax.mcp CodeWarrior (8) project you want to
check out the FluidSynth source tree into a directory on the same level
than (parallel to) this directory.
The following lines have to be added to the fluidsynth_priv.h file:
/* begin fluidsynth_priv.h */
#if defined(__POWERPC__) && !(defined(__APPLE__) && defined(__MACH__))
#include "config_maxmsp43.h"
#endif
/* end fluidsynth_priv.h */
The fluidsynth directory in this directory contains only a version.h
which is just added for the case that the version.h file in the
fluidsynth checkout is not (auto-)"maked" or generated otherwise.
For now the file fluid_sys.c is not included to the CW project.
Instead there (here) is a file called fluidmax_fakefuns.c implementing
some necessary functions.
Using fluid_sys.c with the macro MACOS 9 defined almost works.
Its only the prototype of the function NewTimerProc() causing a
compilation error (no prototype) and didn't find any good include
to fix this...
The following three functions used in fluid_settings are missing:
fluid_shell_settings()
fluid_audio_driver_settings()
fluid_midi_driver_settings()
KNOWN BUGS:
- Unloading SoungFonts doesn't work (would probably be fixed if using the MACOS 9 macro)
TODO
- get rid of fluidmax_fakefuns.c
- implement log function properly
- fix unloading
- allow access to SFs by name (rather than id only)
- avoid double loading of Sfs and loading of SFs with the same name

View file

@ -0,0 +1,16 @@
#define MACINTOSH
#define MACOS9
#define HAVE_STRING_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STDIO_H 1
#define HAVE_MATH_H 1
#define HAVE_STDARG_H 1
#define WORDS_BIGENDIAN 1
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#undef WITH_PROFILING
#define __Types__

View file

@ -0,0 +1,957 @@
/***************************************************************************************
*
* fluidsynth~
*
* Fluid Synth soundfont synthesizer for Max/MSP.
*
* Fluid Synth is written by Peter Hanappe et al.
* see http://www.fluidsynth.org/
*
* Max/MSP integration by Norbert Schnell ATR IRCAM - Centre Pompidou
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* See file COPYING.LIB for further informations on licensing terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "ftmax.h"
#include "fluidsynth.h"
#include "fluid_synth.h"
#include "fluid_sfont.h"
#include "fluid_chan.h"
/************************************************************************
*
* These functions were added after the v1.0 API freeze. They are not
* in synth.h, yet.
*
************************************************************************/
int fluid_synth_program_select2(fluid_synth_t* synth,
int chan,
char* sfont_name,
unsigned int bank_num,
unsigned int preset_num);
#define VERSION "02/2004 (3)"
typedef struct
{
ftmax_dsp_object_t obj;
fluid_synth_t *synth;
fluid_settings_t *settings;
int mute;
void *outlet;
} fluidmax_t;
static t_messlist *fluidmax_class;
static ftmax_symbol_t sym_on = NULL;
static ftmax_symbol_t sym_off = NULL;
/***************************************************************
*
* dsp
*
*/
static t_int *
fluidmax_perform(t_int *w)
{
fluidmax_t *self = (fluidmax_t *)(w[1]);
t_float *left = (t_float *)(w[2]);
t_float *right = (t_float *)(w[3]);
int n_tick = (int)(w[4]);
if(self->mute == 0)
fluid_synth_write_float(self->synth, n_tick, left, 0, 1, right, 0, 1);
else
{
int i;
for(i=0; i<n_tick; i++)
left[i] = right[i] = 0.0;
}
return (w + 5);
}
static void
fluidmax_dsp(fluidmax_t *self, t_signal **sp, short *count)
{
double sr = sp[0]->s_sr;
int n_tick = sp[0]->s_n;
dsp_add(fluidmax_perform, 4, self, sp[0]->s_vec, sp[1]->s_vec, n_tick);
}
/***************************************************************
*
* load utlilities
*
*/
static void
fluidmax_do_load(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_symbol(at))
{
const char* filename = ftmax_symbol_name(ftmax_get_symbol(at));
if(fluid_synth_sfload(self->synth, filename, 0) >= 0)
{
post("fluidsynth~: loaded soundfont: %s", filename);
fluid_synth_program_reset(self->synth);
outlet_bang(self->outlet);
}
else
error("fluidsynth~: cannot load soundfont from file: %s", filename);
}
}
static char *
fluidmax_translate_fullpath(char *fullpath)
{
char last = '/';
int i;
for(i=0; fullpath[i] != '\0'; i++)
{
char c = fullpath[i];
fullpath[i] = last;
if(c == ':')
break;
last = c;
}
return fullpath;
}
static void
fluidmax_load_with_dialog(t_object *o, t_symbol *s, short argc, t_atom *argv)
{
char filename[256];
char fullname[1024];
long type;
short path;
open_promptset("open SoundFont 2 file");
if(open_dialog(filename, &path, &type, 0, 0))
return;
if(path_topotentialname(path, filename, fullname, 0) == 0)
{
ftmax_atom_t a;
ftmax_set_symbol(&a, ftmax_new_symbol(fluidmax_translate_fullpath(fullname)));
fluidmax_do_load(o, NULL, 1, &a);
}
}
/***************************************************************
*
* user methods
*
*/
static void
fluidmax_load(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac == 0)
defer(o, (method)fluidmax_load_with_dialog, NULL, 0, 0);
else
{
if(ftmax_is_symbol(at))
{
ftmax_symbol_t name = ftmax_get_symbol(at);
char *string = (char *)ftmax_symbol_name(name);
if(string[0] == '/')
fluidmax_do_load(o, NULL, ac, at);
else
{
char fullname[1024];
short path;
long type;
ftmax_atom_t a;
if(locatefile_extended(string, &path, &type, 0, 0) || path_topotentialname(path, string, fullname, 0) != 0)
{
error("fluidmax~: cannot find file '%s'", string);
return;
}
ftmax_set_symbol(&a, ftmax_new_symbol(fluidmax_translate_fullpath(fullname)));
fluidmax_do_load(o, NULL, 1, &a);
}
}
}
}
static void
fluidmax_unload(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0)
{
if(ftmax_is_number(at))
{
int id = ftmax_get_number_int(at);
fluid_sfont_t *sf = fluid_synth_get_sfont_by_id(self->synth, id);
if(sf != NULL)
{
char *name = fluid_sfont_get_name(sf);
if(fluid_synth_sfunload(self->synth, id, 0) >= 0)
{
post("fluidsynth~: unloaded soundfont %d: %s", id, name);
return;
}
}
error("fluidsynth~: cannot unload soundfont %d", id);
}
else if (ftmax_is_symbol(at))
{
ftmax_symbol_t sym = ftmax_get_symbol(at);
if(sym == ftmax_new_symbol("all"))
{
int n = fluid_synth_sfcount(self->synth);
int i;
fluid_synth_system_reset(self->synth);
for(i=0; i<n; i++)
{
fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, i);
char *name = fluid_sfont_get_name(sf);
unsigned int id = fluid_sfont_get_id(sf);
post("fluidsynth~: unloaded soundfont %d", id);
}
}
}
}
}
static void
fluidmax_reload(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int id = ftmax_get_number_int(at);
if (fluid_synth_sfreload(self->synth, id) >= 0)
post("fluidsynth~: reloaded soundfont %d", id);
else
error("fluidsynth~: cannot reload soundfont %d", id);
}
}
static void
fluidmax_note(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int velocity = 64;
int channel = 1;
switch(ac)
{
default:
case 3:
if(ftmax_is_number(at + 2))
{
channel = ftmax_get_number_int(at + 2);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
}
case 2:
if(ftmax_is_number(at + 1))
velocity = ftmax_get_number_int(at + 1);
case 1:
fluid_synth_noteon(self->synth, channel - 1, ftmax_get_number_int(at), velocity);
case 0:
break;
}
}
}
static void
fluidmax_list(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_note(o, NULL, ac, at);
}
static void
fluidmax_control_change(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int value = 64;
int channel = 1;
switch(ac)
{
default:
case 3:
if(ftmax_is_number(at + 2))
{
channel = ftmax_get_number_int(at + 2);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
}
case 2:
if(ftmax_is_number(at + 1))
value = ftmax_get_number_int(at + 1);
case 1:
fluid_synth_cc(self->synth, channel - 1, ftmax_get_number_int(at), value);
case 0:
break;
}
}
}
static void
fluidmax_mod(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 1 && ftmax_is_number(at) && ftmax_is_number(at + 1))
{
int param = ftmax_get_number_int(at);
float value = ftmax_get_number_float(at + 1);
int channel = 1;
if(ac > 2 && ftmax_is_number(at + 2))
{
channel = ftmax_get_number_int(at + 2);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
}
fluid_synth_set_gen(self->synth, channel - 1, param, value);
}
}
static void
fluidmax_pitch_bend(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int channel = 1;
double bend = 0.0;
if(ac > 1 && ftmax_is_number(at + 1))
{
channel = ftmax_get_number_int(at + 1);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
}
bend = ftmax_get_number_float(at);
if(bend < 0.0)
bend = 0.0;
else if(bend > 127.0)
bend = 127.0;
fluid_synth_pitch_bend(self->synth, channel - 1, (int)(bend * 128.0));
}
}
static void
fluidmax_pitch_bend_wheel(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int channel = 1;
if(ac > 1 && ftmax_is_number(at + 1))
channel = ftmax_get_number_int(at + 1);
fluid_synth_pitch_wheel_sens(self->synth, channel - 1, ftmax_get_number_int(at));
}
}
static void
fluidmax_program_change(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int channel = 1;
if(ac > 1 && ftmax_is_number(at + 1))
{
channel = ftmax_get_number_int(at + 1);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
}
fluid_synth_program_change(self->synth, channel - 1, ftmax_get_number_int(at));
}
}
static void
fluidmax_bank_select(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0 && ftmax_is_number(at))
{
int channel = 1;
if(ac > 1 && ftmax_is_number(at + 1))
{
channel = ftmax_get_number_int(at + 1);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
}
fluid_synth_bank_select(self->synth, channel - 1, ftmax_get_number_int(at));
}
}
static void
fluidmax_select(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
unsigned int sfont = 0;
unsigned int bank = 0;
unsigned int preset = 0;
int channel = 1;
if (ac == 0)
{
return; // Someone is wasting our time
}
if(ftmax_is_number(at))
{
switch(ac)
{
default:
case 4:
if(ftmax_is_number(at + 3))
channel = ftmax_get_number_int(at + 3);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
case 3:
if(ftmax_is_number(at + 2))
preset = ftmax_get_number_int(at + 2);
case 2:
if(ftmax_is_number(at + 1))
bank = ftmax_get_number_int(at + 1);
case 1:
fluid_synth_program_select(self->synth, channel - 1, ftmax_get_number_int(at), bank, preset);
case 0:
break;
}
} else if(ftmax_is_symbol(at)) {
ftmax_symbol_t tmp = ftmax_get_symbol(at);
char *name = (char *)ftmax_symbol_name(tmp);
// FIXME: this is silly code duplication
switch(ac)
{
default:
case 4:
if(ftmax_is_number(at + 3))
channel = ftmax_get_number_int(at + 3);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
case 3:
if(ftmax_is_number(at + 2))
preset = ftmax_get_number_int(at + 2);
case 2:
if(ftmax_is_number(at + 1))
bank = ftmax_get_number_int(at + 1);
case 1:
fluid_synth_program_select2(self->synth, channel - 1, name, bank, preset);
case 0:
break;
}
}
}
static void
fluidmax_reverb(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac == 0)
{
fluid_synth_set_reverb_on(self->synth, 1);
fluid_revmodel_reset(self->synth->reverb);
}
else if(ftmax_is_number(at))
{
double room = fluid_synth_get_reverb_roomsize(self->synth);
double damping = fluid_synth_get_reverb_damp(self->synth);
double width = fluid_synth_get_reverb_width(self->synth);
fluid_synth_set_reverb_on(self->synth, 1);
switch(ac)
{
default:
case 4:
if(ftmax_is_number(at + 3))
width = ftmax_get_number_float(at + 3);
case 3:
if(ftmax_is_number(at + 2))
damping = ftmax_get_number_float(at + 2);
case 2:
if(ftmax_is_number(at + 1))
room = ftmax_get_number_float(at + 1);
case 1:
fluid_synth_set_reverb(self->synth, room, damping, width, ftmax_get_number_float(at));
case 0:
break;
}
}
else if(ftmax_is_symbol(at))
{
ftmax_symbol_t sym = ftmax_get_symbol(at);
if(sym == sym_on)
fluid_synth_set_reverb_on(self->synth, 1);
else if(sym == sym_off)
fluid_synth_set_reverb_on(self->synth, 0);
}
}
static void
fluidmax_chorus(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac == 0)
{
fluid_synth_set_chorus_on(self->synth, 1);
fluid_chorus_reset(self->synth->chorus);
}
else if(ftmax_is_number(at))
{
double speed = fluid_synth_get_chorus_speed_Hz(self->synth);
double depth = fluid_synth_get_chorus_depth_ms(self->synth);
int type = fluid_synth_get_chorus_type(self->synth);
int nr = fluid_synth_get_chorus_nr(self->synth);
fluid_synth_set_chorus_on(self->synth, 1);
switch(ac)
{
default:
case 5:
if(ftmax_is_number(at + 4))
nr = ftmax_get_number_int(at + 4);
case 4:
if(ftmax_is_number(at + 3))
type = ftmax_get_number_int(at + 3);
case 3:
if(ftmax_is_number(at + 2))
depth = ftmax_get_number_float(at + 2);
case 2:
if(ftmax_is_number(at + 1))
speed = ftmax_get_number_float(at + 1);
case 1:
fluid_synth_set_chorus(self->synth, nr, ftmax_get_number_float(at), speed, depth, type);
case 0:
break;
}
}
else if(ftmax_is_symbol(at))
{
ftmax_symbol_t sym = ftmax_get_symbol(at);
if(sym == sym_on)
fluid_synth_set_chorus_on(self->synth, 1);
else if(sym == sym_off)
fluid_synth_set_chorus_on(self->synth, 0);
}
}
static void
fluidmax_gain(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac >0 && ftmax_is_number(at))
{
float gain = ftmax_get_number_float(at);
fluid_synth_set_gain(self->synth, gain);
}
}
static void
fluidmax_panic(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
fluid_synth_system_reset(self->synth);
}
static void
fluidmax_reset(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
int n = fluid_synth_count_midi_channels(self->synth);
int i;
for (i=0; i<n; i++)
fluid_channel_reset(self->synth->channel[i]);
}
static void
fluidmax_mute(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
int mute = 1;
int i;
if(ac > 0 && ftmax_is_number(at))
mute = (ftmax_get_number_int(at) != 0);
fluid_synth_system_reset(self->synth);
self->mute = mute;
}
static void
fluidmax_unmute(t_object *o)
{
fluidmax_t *self = (fluidmax_t *)o;
ftmax_atom_t a;
ftmax_set_int(&a, 0);
fluidmax_mute(o, NULL, 1, &a);
}
/*
int fluid_synth_count_audio_channels (fluid_synth_t *synth)
int fluid_synth_count_audio_groups (fluid_synth_t *synth)
int fluid_synth_count_effects_channels (fluid_synth_t *synth)
*/
/* tuning
fluid_synth_create_key_tuning (fluid_synth_t *synth, int tuning_bank, int tuning_prog, char *name, double *pitch)
fluid_synth_create_octave_tuning (fluid_synth_t *synth, int tuning_bank, int tuning_prog, char *name, double *pitch)
fluid_synth_tune_notes (fluid_synth_t *synth, int tuning_bank, int tuning_prog, int len, int *keys, double *pitch, int apply)
fluid_synth_select_tuning (fluid_synth_t *synth, int chan, int tuning_bank, int tuning_prog)
fluid_synth_reset_tuning (fluid_synth_t *synth, int chan)
fluid_synth_tuning_iteration_start (fluid_synth_t *synth)
fluid_synth_tuning_iteration_next (fluid_synth_t *synth, int *bank, int *prog)
fluid_synth_tuning_dump (fluid_synth_t *synth, int bank, int prog, char *name, int len, double *pitch)
*/
static void
fluidmax_version(t_object *o)
{
post("fluidsynth~ (Fluid Synth soundfont synthesizer for Max/MSP), version %s", VERSION);
post(" Fluid Synth is written by Peter Hanappe et al. (see http://www.fluidsynth.org/)");
post(" Max/MSP integration by Norbert Schnell ATR IRCAM - Centre Pompidou");
}
static void
fluidmax_print(t_object *o, Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)o;
if(ac > 0)
{
if(ftmax_is_symbol(at))
{
ftmax_symbol_t sym = ftmax_get_symbol(at);
if(sym == ftmax_new_symbol("gain"))
{
double gain = fluid_synth_get_gain(self->synth);
post("gain: %g", gain);
}
else if(sym == ftmax_new_symbol("channels"))
{
int n = fluid_synth_count_midi_channels(self->synth);
int i;
post("fluidsynth~ channels:");
for(i=0; i<n; i++)
{
unsigned int sfont;
unsigned int bank;
unsigned int preset;
fluid_synth_get_program(self->synth, i, &sfont, &bank, &preset);
post(" %d: font %d, bank %d, preset %d", i + 1, sfont, bank, preset);
/*fluid_preset_t *fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan);*/
}
}
else if(sym == ftmax_new_symbol("soundfonts"))
{
int n = fluid_synth_sfcount(self->synth);
int i;
if(n > 0)
post("fluidsynth~ soundfonts:");
else
post("fluidsynth~: no soundfonts loaded");
for(i=0; i<n; i++)
{
fluid_sfont_t *sf = fluid_synth_get_sfont(self->synth, i);
char *name = fluid_sfont_get_name(sf);
unsigned int id = fluid_sfont_get_id(sf);
post(" %d: %s", id, name);
/*fluid_preset_t *preset = fluid_sfont_get_preset(sf, bank, preset);*/
}
}
else if(sym == ftmax_new_symbol("modulators"))
{
int channel = 1;
int n = GEN_LAST;
int i;
if(ac > 1 && ftmax_is_number(at + 1))
channel = ftmax_get_number_int(at + 1);
if(channel < 1)
channel = 1;
else if(channel > fluid_synth_count_midi_channels(self->synth))
channel = fluid_synth_count_midi_channels(self->synth);
post("fluidsynth~ modulator states of channel %d:", channel);
for(i=0; i<n; i++)
post(" %d: %f", i, fluid_synth_get_gen(self->synth, channel - 1, i));
}
else if(sym == ftmax_new_symbol("reverb"))
{
double level = fluid_synth_get_reverb_level(self->synth);
double room = fluid_synth_get_reverb_roomsize(self->synth);
double damping = fluid_synth_get_reverb_damp(self->synth);
double width = fluid_synth_get_reverb_width(self->synth);
post("fluidsynth~ current reverb parameters:");
post(" level: %f", level);
post(" room size: %f", room);
post(" damping: %f", damping);
post(" width: %f", width);
}
else if(sym == ftmax_new_symbol("chorus"))
{
double level = fluid_synth_get_chorus_level(self->synth);
double speed = fluid_synth_get_chorus_speed_Hz(self->synth);
double depth = fluid_synth_get_chorus_depth_ms(self->synth);
int type = fluid_synth_get_chorus_type(self->synth);
int nr = fluid_synth_get_chorus_nr(self->synth);
post("fluidsynth~ current chorus parameters:");
post(" level: %f", level);
post(" speed: %f Hz", speed);
post(" depth: %f msec", depth);
post(" type: %d (%s)", type, type? "triangle": "sine");
post(" %d units", nr);
}
}
}
}
/***************************************************************
*
* class
*
*/
static void *
fluidmax_new(Symbol *s, short ac, Atom *at)
{
fluidmax_t *self = (fluidmax_t *)newobject(fluidmax_class);
int polyphony = 256;
int midi_channels = 16;
post("fluidsynth~: DEBUG VERSION [PH]");
self->outlet = outlet_new(self, "bang");
dsp_setup((t_pxobject *)self, 0);
outlet_new(self, "signal");
outlet_new(self, "signal");
self->synth = NULL;
self->settings = new_fluid_settings();
self->mute = 0;
if(ac > 0 && ftmax_is_number(at))
{
polyphony = ftmax_get_number_int(at);
ac--;
at++;
}
if(ac > 0 && ftmax_is_number(at))
{
midi_channels = ftmax_get_number_int(at);
ac--;
at++;
}
if(ac > 0 && ftmax_is_symbol(at))
{
ftmax_symbol_t name = ftmax_get_symbol(at);
fluidmax_load((t_object *)self, NULL, 1, at);
}
if(self->settings != NULL)
{
fluid_settings_setnum(self->settings, "synth.midi-channels", midi_channels);
fluid_settings_setnum(self->settings, "synth.polyphony", polyphony);
fluid_settings_setnum(self->settings, "synth.gain", 0.600000);
fluid_settings_setnum(self->settings, "synth.sample-rate", sys_getsr());
self->synth = new_fluid_synth(self->settings);
if(self->synth != NULL)
{
if(ac > 0 && ftmax_is_symbol(at))
fluidmax_load((t_object *)self, NULL, ac, at);
return self;
}
delete_fluid_settings(self->settings);
}
error("fluidsynth~: cannot create FluidSynth core");
return NULL;
}
static void
fluidmax_free(t_pxobject *o)
{
fluidmax_t *self = (fluidmax_t *)o;
if(self->settings != NULL )
delete_fluid_settings(self->settings);
if(self->synth != NULL )
delete_fluid_synth(self->synth);
dsp_free(o);
}
void
main(void)
{
setup(&fluidmax_class, (method)fluidmax_new, (method)fluidmax_free, (short)sizeof(fluidmax_t), 0, A_GIMME, 0);
dsp_initclass();
addmess((method)fluidmax_dsp, "dsp", A_CANT, 0);
addmess((method)fluidmax_version, "version", 0);
addmess((method)fluidmax_print, "print", A_GIMME, 0);
addmess((method)fluidmax_load, "load", A_GIMME, 0);
addmess((method)fluidmax_unload, "unload", A_GIMME, 0);
addmess((method)fluidmax_reload, "reload", A_GIMME, 0);
addmess((method)fluidmax_panic, "panic", A_GIMME, 0);
addmess((method)fluidmax_reset, "reset", A_GIMME, 0);
addmess((method)fluidmax_mute, "mute", A_GIMME, 0);
addmess((method)fluidmax_unmute, "unmute", 0);
addmess((method)fluidmax_reverb, "reverb", A_GIMME, 0);
addmess((method)fluidmax_chorus, "chorus", A_GIMME, 0);
addmess((method)fluidmax_gain, "gain", A_GIMME, 0);
addmess((method)fluidmax_note, "note", A_GIMME, 0);
addmess((method)fluidmax_list, "list", A_GIMME, 0);
addmess((method)fluidmax_control_change, "control", A_GIMME, 0);
addmess((method)fluidmax_mod, "mod", A_GIMME, 0);
addmess((method)fluidmax_pitch_bend, "bend", A_GIMME, 0);
addmess((method)fluidmax_pitch_bend_wheel, "wheel", A_GIMME, 0);
addmess((method)fluidmax_program_change, "program", A_GIMME, 0);
addmess((method)fluidmax_bank_select, "bank", A_GIMME, 0);
addmess((method)fluidmax_select, "select", A_GIMME, 0);
sym_on = ftmax_new_symbol("on");
sym_off = ftmax_new_symbol("off");
fluidmax_version(NULL);
}

Binary file not shown.

View file

@ -0,0 +1,94 @@
/***************************************************************************************
*
* fluidsynth~
*
* Fluid Synth soundfont synthesizer for Max/MSP.
*
* Fluid Synth is written by Peter Hanappe et al.
* see http://www.fluidsynth.org/
*
* Max/MSP integration by Norbert Schnell ATR IRCAM - Centre Pompidou
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* See file COPYING.LIB for further informations on licensing terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "ftmax.h"
#include "fluidsynth.h"
#include "fluidsynth_priv.h"
#include "fluid_settings.h"
unsigned int
fluid_curtime()
{
return (unsigned int)gettime();
}
double
fluid_utime(void)
{
return 0.0;
}
typedef void fluid_timer_t;
typedef int(*fluid_timer_callback_t)(void* data, unsigned int msec);
fluid_timer_t *
new_fluid_timer(int msec, fluid_timer_callback_t callback, void* data, int new_thread, int auto_destroy)
{
/* just call it right away */
(*callback)(data, msec);
return NULL;
}
void
fluid_sys_config()
{
}
int
fluid_log(int level, char* fmt, ...)
{
char buf[1024];
va_list args;
va_start (args, fmt);
vsprintf(buf, fmt, args);
va_end (args);
if ((level >= 0) && (level < LAST_LOG_LEVEL))
post("fluidsynth~: %s", buf);
return -1;
}
void
fluid_shell_settings(fluid_settings_t *settings)
{
}
void
fluid_audio_driver_settings(fluid_settings_t *settings)
{
fluid_settings_register_str(settings, "audio.driver", "", 0, NULL, NULL);
}
void
fluid_midi_driver_settings(fluid_settings_t *settings)
{
fluid_settings_register_str(settings, "midi.driver", "", 0, NULL, NULL);
}

View file

@ -0,0 +1,44 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#ifndef _FLUIDSYNTH_VERSION_H
#define _FLUIDSYNTH_VERSION_H
#ifdef __cplusplus
extern "C" {
#endif
#define FLUIDSYNTH_VERSION "1.0.3"
#define FLUIDSYNTH_VERSION_MAJOR 1
#define FLUIDSYNTH_VERSION_MINOR 0
#define FLUIDSYNTH_VERSION_MICRO 3
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);
FLUIDSYNTH_API char* fluid_version_str(void);
#ifdef __cplusplus
}
#endif
#endif /* _FLUIDSYNTH_VERSION_H */

View file

@ -0,0 +1,76 @@
/***************************************************************************************
*
* Copyright (C) 2004 by IRCAM-Centre Georges Pompidou, Paris, France.
* Author: Norbert.Schnell@ircam.fr
*
* FTS -> MAX/MSP utilities
*
*/
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* See file COPYING.LIB for further informations on licensing terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _FTMAX_H_
#define _FTMAX_H_
#include <stdlib.h>
#ifndef MAGIC
#include "ext.h"
#include "z_dsp.h"
#endif
#define ftm_malloc(s) NewPtr(s)
#define ftmax_realloc NO_realloc
#define ftmax_free(p) DisposePtr((char *)(p))
#define restrict
#define M_TWOPI 6.283185308
#define M_PI 3.141592654
#define ftmax_object_t t_object
#define ftmax_dsp_object_t t_pxobject
typedef t_atom ftmax_atom_t;
typedef t_symbol *ftmax_symbol_t;
typedef t_messlist ftmax_class_t;
typedef method ftmax_method_t;
#define ftmax_is_int(a) ((a)->a_type == A_LONG)
#define ftmax_is_float(a) ((a)->a_type == A_FLOAT)
#define ftmax_is_number(a) ((a)->a_type == A_LONG || (a)->a_type == A_FLOAT)
#define ftmax_is_symbol(a) ((a)->a_type == A_SYM)
#define ftmax_get_int(a) ((a)->a_w.w_long)
#define ftmax_get_float(a) ((a)->a_w.w_float)
#define ftmax_get_number_int(a) (((a)->a_type == A_LONG)? ((a)->a_w.w_long): (int)((a)->a_w.w_float))
#define ftmax_get_number_float(a) (((a)->a_type == A_FLOAT)? (double)((a)->a_w.w_float): (double)((a)->a_w.w_long))
#define ftmax_get_symbol(a) ((a)->a_w.w_sym)
#define ftmax_set_int(a, v) ((a)->a_type = A_LONG, (a)->a_w.w_long = (v))
#define ftmax_set_float(a, v) ((a)->a_type = A_FLOAT, (a)->a_w.w_float = (v))
#define ftmax_set_symbol(a, v) ((a)->a_type = A_SYM, (a)->a_w.w_sym = (v))
#define ftmax_symbol_name(s) ((s)->s_name)
#define ftmax_new_symbol(s) gensym(s)
extern void ftmax_class_message_varargs(ftmax_class_t *cl, ftmax_symbol_t sym, void *method);
#endif

Binary file not shown.

View file

@ -0,0 +1,10 @@
FluidSynth_JNI
--------------
This directory contains a VC++ project, Java classes, and some C++
files to use FluidSynth from within Java. This project was written
rather quickly and for a specific use. Is not intended to be complete
but may be useful as a starting point for complete Java interface.
[Peter Hanappe]

View file

@ -0,0 +1,115 @@
# Microsoft Developer Studio Project File - Name="fluidsynth_jni" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=fluidsynth_jni - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "fluidsynth_jni.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "fluidsynth_jni.mak" CFG="fluidsynth_jni - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "fluidsynth_jni - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "fluidsynth_jni - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "fluidsynth_jni - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLUIDSYNTH_JNI_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "include" /I "C:\Program Files\Java\j2re1.4.0_03\include" /I "C:\Program Files\Java\j2re1.4.0_03\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLUIDSYNTH_JNI_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "NDEBUG"
# ADD RSC /l 0x40c /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 fluidsynth.lib libsndfile.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"lib"
!ELSEIF "$(CFG)" == "fluidsynth_jni - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLUIDSYNTH_JNI_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "include" /I "C:\Program Files\WebGain\VCafe\Java2\include" /I "C:\Program Files\WebGain\VCafe\Java2\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FLUIDSYNTH_JNI_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "_DEBUG"
# ADD RSC /l 0x40c /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 fluidsynth_debug.lib libsndfile.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"fluidsynth_jni.dll" /pdbtype:sept /libpath:"lib"
!ENDIF
# Begin Target
# Name "fluidsynth_jni - Win32 Release"
# Name "fluidsynth_jni - Win32 Debug"
# Begin Source File
SOURCE=.\src\fluidsynth_jni.cpp
# End Source File
# Begin Source File
SOURCE=.\src\fluidsynth_jni.h
# End Source File
# Begin Source File
SOURCE=.\src\fluidsynth_Sample.cpp
# End Source File
# Begin Source File
SOURCE=.\src\fluidsynth_Sample.h
# End Source File
# Begin Source File
SOURCE=.\src\fluidsynth_Synth.cpp
# End Source File
# Begin Source File
SOURCE=.\src\fluidsynth_Synth.h
# End Source File
# End Target
# End Project

View file

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "fluidsynth_jni"=".\fluidsynth_jni.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

@ -0,0 +1,426 @@
/*
** Copyright (C) 1999-2003 Erik de Castro Lopo <erikd@zip.com.au>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** sndfile.h -- system-wide definitions
**
** API documentation is in the doc/ directory of the source code tarball
** and at http://www.zip.com.au/~erikd/libsndfile/api.html.
*/
#ifndef SNDFILE_H
#define SNDFILE_H
/* This is the version 1.0.X header file. */
#define SNDFILE_1
#include <stdio.h>
#include <stdlib.h>
/* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */
#if (defined (__MWERKS__))
#include <unix.h>
#else
#include <sys/types.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* The following file types can be read and written.
** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise
** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and
** SF_FORMAT_SUBMASK can be used to separate the major and minor file
** types.
*/
enum
{ /* Major formats. */
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian). */
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
SF_FORMAT_VOC = 0x080000, /* VOC files. */
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
/* Subtypes from here on. */
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */
SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */
SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */
SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */
SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */
SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */
SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */
SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */
SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */
SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */
SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */
SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */
SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */
SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */
SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */
SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */
SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */
SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */
/* Endian-ness options. */
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */
SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */
SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */
SF_FORMAT_SUBMASK = 0x0000FFFF,
SF_FORMAT_TYPEMASK = 0x0FFF0000,
SF_FORMAT_ENDMASK = 0x30000000
} ;
/*
** The following are the valid command numbers for the sf_command()
** interface. The use of these commands is documented in the file
** command.html in the doc directory of the source code distribution.
*/
enum
{ SFC_GET_LIB_VERSION = 0x1000,
SFC_GET_LOG_INFO = 0x1001,
SFC_GET_NORM_DOUBLE = 0x1010,
SFC_GET_NORM_FLOAT = 0x1011,
SFC_SET_NORM_DOUBLE = 0x1012,
SFC_SET_NORM_FLOAT = 0x1013,
SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020,
SFC_GET_SIMPLE_FORMAT = 0x1021,
SFC_GET_FORMAT_INFO = 0x1028,
SFC_GET_FORMAT_MAJOR_COUNT = 0x1030,
SFC_GET_FORMAT_MAJOR = 0x1031,
SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032,
SFC_GET_FORMAT_SUBTYPE = 0x1033,
SFC_CALC_SIGNAL_MAX = 0x1040,
SFC_CALC_NORM_SIGNAL_MAX = 0x1041,
SFC_CALC_MAX_ALL_CHANNELS = 0x1042,
SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043,
SFC_SET_ADD_PEAK_CHUNK = 0x1050,
SFC_UPDATE_HEADER_NOW = 0x1060,
SFC_SET_UPDATE_HEADER_AUTO = 0x1061,
SFC_FILE_TRUNCATE = 0x1080,
SFC_SET_RAW_START_OFFSET = 0x1090,
SFC_SET_DITHER_ON_WRITE = 0x10A0,
SFC_SET_DITHER_ON_READ = 0x10A1,
SFC_GET_DITHER_INFO_COUNT = 0x10A2,
SFC_GET_DITHER_INFO = 0x10A3,
SFC_GET_EMBED_FILE_INFO = 0x10B0,
/* Following commands for testing only. */
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
/*
** SFC_SET_ADD_* values are deprecated and will disappear at some
** time in the future. They are guaranteed to be here up to and
** including version 1.0.8 to avoid breakage of existng software.
** They currently do nothing and will continue to do nothing.
*/
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
SFC_SET_ADD_DITHER_ON_READ = 0x1071
} ;
/*
** String types that can be set and read from files. Not all file types
** support this and even the file types which support one, may not support
** all string types.
*/
enum
{ SF_STR_TITLE = 0x01,
SF_STR_COPYRIGHT = 0x02,
SF_STR_SOFTWARE = 0x03,
SF_STR_ARTIST = 0x04,
SF_STR_COMMENT = 0x05,
SF_STR_DATE = 0x06
} ;
enum
{ /* True and false */
SF_FALSE = 0,
SF_TRUE = 1,
/* Modes for opening files. */
SFM_READ = 0x10,
SFM_WRITE = 0x20,
SFM_RDWR = 0x30
} ;
/* Pubic error values. These are guaranteed to remain unchanged for the duration
** of the library major version number.
** There are also a large number of private error numbers which are internal to
** the library which can change at any time.
*/
enum
{ SF_ERR_NO_ERROR = 0,
SF_ERR_UNRECOGNISED_FORMAT = 1,
SF_ERR_SYSTEM = 2
} ;
/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */
typedef void SNDFILE ;
typedef __int64 sf_count_t ;
/* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in.
** On write, the SF_INFO structure is filled in by the user and passed into
** sf_open_write ().
*/
struct SF_INFO
{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */
int samplerate ;
int channels ;
int format ;
int sections ;
int seekable ;
} ;
typedef struct SF_INFO SF_INFO ;
/* The SF_FORMAT_INFO struct is used to retrieve information about the sound
** file formats libsndfile supports using the sf_command () interface.
**
** Using this interface will allow applications to support new file formats
** and encoding types when libsndfile is upgraded, without requiring
** re-compilation of the application.
**
** Please consult the libsndfile documentation (particularly the information
** on the sf_command () interface) for examples of its use.
*/
typedef struct
{ int format ;
const char *name ;
const char *extension ;
} SF_FORMAT_INFO ;
/*
** Enums and typedefs for adding dither on read and write.
** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
** and SFC_SET_DITHER_ON_READ.
*/
enum
{ SFD_DEFAULT_LEVEL = 0,
SFD_CUSTOM_LEVEL = 0x40000000,
SFD_NO_DITHER = 500,
SFD_WHITE = 501,
SFD_TRIANGULAR_PDF = 502
} ;
typedef struct
{ int type ;
double level ;
const char *name ;
} SF_DITHER_INFO ;
/* Struct used to retrieve information about a file embedded within a
** larger file. See SF_GET_EMBED_FILE_INFO.
*/
typedef struct
{ sf_count_t offset ;
sf_count_t length ;
} SF_EMBED_FILE_INFO ;
/* Open the specified file for read, write or both. On error, this will
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
** to sf_perror () or sf_error_str ().
** All calls to sf_open() should be matched with a call to sf_close().
*/
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;
/* Use the existing file descriptor to create a SNDFILE object. If close_desc
** is TRUE, the file descriptor will be closed when sf_close() is called. If
** it is FALSE, the descritor will not be closed.
** When passed a descriptor like this, the library will assume that the start
** of file header is at the current file offset. This allows sound files within
** larger container files to be read and/or written.
** On error, this will return a NULL pointer. To find the error number, pass a
** NULL SNDFILE to sf_perror () or sf_error_str ().
** All calls to sf_open_fd() should be matched with a call to sf_close().
*/
SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
/* sf_error () returns a error number which can be translated to a text
** string using sf_error_number().
*/
int sf_error (SNDFILE *sndfile) ;
/* sf_strerror () returns to the caller a pointer to the current error message for
** the given SNDFILE.
*/
const char* sf_strerror (SNDFILE *sndfile) ;
/* sf_error_number () allows the retrieval of the error string for each internal
** error number.
**
*/
const char* sf_error_number (int errnum) ;
/* The following three error functions are deprecated but they will remain in the
** library for the forseeable future. The function sf_strerror() should be used
** in their place.
*/
int sf_perror (SNDFILE *sndfile) ;
int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ;
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
int sf_format_check (const SF_INFO *info) ;
/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
** stdio.h function fseek ().
** An offset of zero with whence set to SEEK_SET will position the
** read / write pointer to the first data sample.
** On success sf_seek returns the current position in (multi-channel)
** samples from the start of the file.
** Please see the libsndfile documentation for moving the read pointer
** separately from the write pointer on files open in mode SFM_RDWR.
** On error all of these functions return -1.
*/
sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ;
/* Functions for retrieving and setting string data within sound files.
** Not all file types support this features; AIFF and WAV do. For both
** functions, the str_type parameter must be one of the SF_STR_* values
** defined above.
** On error, sf_set_string() returns non-zero while sf_get_string()
** returns NULL.
*/
int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
/* Functions for reading/writing the waveform data of a sound file.
*/
sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
/* Functions for reading and writing the data chunk in terms of frames.
** The number of items actually read/written = frames * number of channels.
** sf_xxxx_raw read/writes the raw data bytes from/to the file
** sf_xxxx_short passes data in the native short format
** sf_xxxx_int passes data in the native int format
** sf_xxxx_float passes data in the native float format
** sf_xxxx_double passes data in the native double format
** All of these read/write function return number of frames read/written.
*/
sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
sf_count_t sf_writef_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
sf_count_t sf_writef_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
sf_count_t sf_writef_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
sf_count_t sf_writef_double(SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
/* Functions for reading and writing the data chunk in terms of items.
** Otherwise similar to above.
** All of these read/write function return number of items read/written.
*/
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
sf_count_t sf_write_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
sf_count_t sf_write_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
sf_count_t sf_write_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
/* Close the SNDFILE and clean up all memory allocations associated with this
** file.
** Returns 0 on success, or an error number.
*/
int sf_close (SNDFILE *sndfile) ;
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* SNDFILE_H */

View file

@ -0,0 +1,8 @@
package fluidsynth;
public class FluidException extends Exception
{
public FluidException(String what) {
super(what);
}
}

View file

@ -0,0 +1,39 @@
package fluidsynth;
public class Sample
{
protected int sampleNum = -1;
protected int rootkey;
protected String filename;
public Sample(String filename, int rootkey) throws FluidException {
sampleNum = newSample(filename, rootkey);
if (sampleNum < 0) {
throw new FluidException("Failed to load the sample (err=" + sampleNum + ")");
}
this.filename = filename;
this.rootkey = rootkey;
}
protected void finalize() {
if (sampleNum >= 0) {
deleteSample(sampleNum);
sampleNum = -1;
}
}
public int getRootKey() {
return rootkey;
}
public String getFileName() {
return filename;
}
int getSampleNum() {
return sampleNum;
}
protected native int newSample(String filename, int rootkey);
protected native void deleteSample(int sampleNum);
}

View file

@ -0,0 +1,49 @@
package fluidsynth;
public class Synth
{
protected int synth = -1;
static {
System.loadLibrary("fluidsynth_jni");
}
public Synth() throws FluidException {
synth = newSynth();
if (synth < 0) {
throw new FluidException("Low-level initialization of the synthesizer failed");
}
}
protected void finalize() {
if (synth >= 0) {
deleteSynth(synth);
synth = -1;
}
}
public void add(Sample sample, int bank, int preset, int lokey, int hikey) throws FluidException {
if (add(synth, sample.getSampleNum(), bank, preset, lokey, hikey) != 0) {
throw new FluidException("Failed to add the sample");
}
}
public void remove(Sample sample, int bank, int preset) throws FluidException {
if (remove(synth, sample.getSampleNum(), bank, preset) != 0) {
throw new FluidException("Failed to remove the sample");
}
}
public void loadSoundFont(String filename) throws FluidException {
if (loadSoundFont(synth, filename) != 0) {
throw new FluidException("Failed to load the SoundFont");
}
}
protected native int newSynth();
protected native void deleteSynth(int synth);
protected native int add(int synth, int sample, int bank,
int preset, int lokey, int hikey);
protected native int remove(int synth, int sample, int bank, int preset);
protected native int loadSoundFont(int synth, String filename);
}

View file

@ -0,0 +1,36 @@
package fluidsynth;
import java.io.*;
public class Test
{
static public void main(String[] argv) throws Exception {
try{
Synth synth = new Synth();
synth.add(new Sample("[accord guitar].wav", 55), 0, 0, 50,58);
synth.add(new Sample("cabrel.wav_14.wav", 60), 0, 0, 59,59);
synth.add(new Sample("cabrel.wav_16.wav", 60), 0, 0, 60,60);
synth.add(new Sample("cabrel.wav_15.wav", 62), 0, 0, 61, 61);
synth.add(new Sample("cabrel.wav_17.wav", 62), 0, 0, 62, 62);
synth.add(new Sample("[TIR].wav", 64), 0, 0, 63,63);
synth.add(new Sample("cabrel.wav_18.wav", 64), 0, 0, 64,64);
synth.add(new Sample("cabrel.wav_5.wav", 64), 0, 0, 65,65);
synth.add(new Sample("cabrel.wav_7.wav", 64), 0, 0, 66,66);
synth.add(new Sample("cabrel.wav_8.wav", 64), 0, 0, 67,67);
synth.add(new Sample("cabrel.wav_19.wav", 64), 0, 0, 68,68);
synth.add(new Sample("cabrel.wav_9.wav", 65), 0, 0, 69,69);
synth.add(new Sample("cabrel.wav_10.wav", 67), 0, 0, 70, 70);
synth.add(new Sample("cabrel.wav_11.wav", 69), 0, 0, 71, 71);
waitCR();
}catch(Exception e){System.out.println(e);waitCR();}
}
public static void waitCR() {
System.out.println ("Appuyez sur CR ...");
try {System.in.read();}
catch (IOException e) {System.out.println(e);}
}
}

Binary file not shown.

View file

@ -0,0 +1,17 @@
#include "fluidsynth_Sample.h"
#include "fluidsynth_jni.h"
JNIEXPORT jint JNICALL
Java_fluidsynth_Sample_newSample(JNIEnv *env, jobject obj, jstring filename, jint rootkey)
{
const char *cfilename = env->GetStringUTFChars(filename, 0);
int err = fluid_jni_new_sample(cfilename, rootkey);
env->ReleaseStringUTFChars(filename, cfilename);
return err;
}
JNIEXPORT void JNICALL
Java_fluidsynth_Sample_deleteSample(JNIEnv *env, jobject obj, jint samplenum)
{
fluid_jni_delete_sample(samplenum);
}

View file

@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class fluidsynth_Sample */
#ifndef _Included_fluidsynth_Sample
#define _Included_fluidsynth_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: fluidsynth_Sample
* Method: newSample
* Signature: (Ljava/lang/String;I)I
*/
JNIEXPORT jint JNICALL Java_fluidsynth_Sample_newSample
(JNIEnv *, jobject, jstring, jint);
/*
* Class: fluidsynth_Sample
* Method: deleteSample
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_fluidsynth_Sample_deleteSample
(JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,38 @@
#include "fluidsynth_Synth.h"
#include "fluidsynth_jni.h"
JNIEXPORT jint JNICALL
Java_fluidsynth_Synth_newSynth(JNIEnv *env, jobject obj)
{
return fluid_jni_new_synth();
}
JNIEXPORT void JNICALL
Java_fluidsynth_Synth_deleteSynth(JNIEnv *env, jobject obj, jint synth)
{
fluid_jni_delete_synth(synth);
}
JNIEXPORT jint JNICALL
Java_fluidsynth_Synth_add(JNIEnv *env, jobject obj, jint synth, jint samplenum,
jint bank, jint preset, jint lokey, jint hikey)
{
return fluid_jni_add(samplenum, bank, preset, lokey, hikey);
}
JNIEXPORT jint JNICALL
Java_fluidsynth_Synth_remove(JNIEnv *env, jobject obj, jint synth,
jint samplenum, jint bank, jint preset)
{
return fluid_jni_remove(samplenum, bank, preset);
}
JNIEXPORT jint JNICALL
Java_fluidsynth_Synth_loadSoundFont(JNIEnv *env, jobject obj, jint synth, jstring filename)
{
const char *cfilename = env->GetStringUTFChars(filename, 0);
int err = fluid_jni_sfload(cfilename);
env->ReleaseStringUTFChars(filename, cfilename);
return err;
}

View file

@ -0,0 +1,48 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class fluidsynth_Synth */
#ifndef _Included_fluidsynth_Synth
#define _Included_fluidsynth_Synth
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: fluidsynth_Synth
* Method: newSynth
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_fluidsynth_Synth_newSynth
(JNIEnv *, jobject);
/*
* Class: fluidsynth_Synth
* Method: deleteSynth
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_fluidsynth_Synth_deleteSynth
(JNIEnv *, jobject, jint);
/*
* Class: fluidsynth_Synth
* Method: add
* Signature: (IIIIII)I
*/
JNIEXPORT jint JNICALL Java_fluidsynth_Synth_add
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint);
/*
* Class: fluidsynth_Synth
* Method: remove
* Signature: (IIII)I
*/
JNIEXPORT jint JNICALL Java_fluidsynth_Synth_remove
(JNIEnv *, jobject, jint, jint, jint, jint);
JNIEXPORT jint JNICALL Java_fluidsynth_Synth_loadSoundFont
(JNIEnv *env, jobject obj, jint synth, jstring filename);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,267 @@
#include <sndfile.h>
#include "fluidsynth_jni.h"
const int fluid_jni_maxsamples = 1024;
static int _initialized = 0;
static fluid_settings_t* _settings = 0;
static fluid_synth_t* _synth = 0;
static fluid_audio_driver_t* _adriver = 0;
static fluid_midi_driver_t* _mdriver = 0;
static fluid_sfont_t* _sfloader = 0;
static fluid_sample_t* _sample[fluid_jni_maxsamples];
void fluid_jni_init()
{
if (_initialized == 0) {
_initialized++;
for (int i = 0; i < fluid_jni_maxsamples; i++) {
_sample[i] = 0;
}
}
}
int fluid_jni_new_synth()
{
if (_synth != 0) {
return -1;
}
fluid_jni_init();
_settings = new_fluid_settings();
if (_settings == 0) {
goto error_recovery;
}
fluid_settings_setstr(_settings, "midi.driver", "midishare");
_synth = new_fluid_synth(_settings);
if (_synth == 0) {
goto error_recovery;
}
_adriver = new_fluid_audio_driver(_settings, _synth);
if (_adriver == 0) {
goto error_recovery;
}
_mdriver = new_fluid_midi_driver(_settings, fluid_synth_handle_midi_event, _synth);
if (_mdriver == 0) {
goto error_recovery;
}
_sfloader = fluid_ramsfont_create_sfont();
if (_sfloader == 0) {
goto error_recovery;
}
fluid_ramsfont_set_name((fluid_ramsfont_t*) _sfloader->data, "Tada");
fluid_synth_add_sfont(_synth, _sfloader);
return 0;
error_recovery:
fluid_jni_delete_synth(0);
return -1;
}
int fluid_jni_delete_synth(int num)
{
if (_mdriver) {
delete_fluid_midi_driver(_mdriver);
_mdriver = 0;
}
if (_adriver) {
delete_fluid_audio_driver(_adriver);
_adriver = 0;
}
if (_synth) {
delete_fluid_synth(_synth);
_synth = 0;
}
if (_settings) {
delete_fluid_settings(_settings);
_settings = 0;
}
return 0;
}
int fluid_jni_sfload(const char* filename)
{
if (_synth == 0) {
return -1;
}
fluid_synth_sfload(_synth, filename, 1);
return 0;
}
int fluid_jni_add(int samplenum, int bank, int preset, int lokey, int hikey)
{
if (_synth == 0) {
return -1;
}
if (_sfloader == 0) {
return -1;
}
fluid_sample_t* sample = fluid_jni_get_sample(samplenum);
if (sample == 0) {
return -2;
}
if (fluid_ramsfont_add_izone((fluid_ramsfont_t*) _sfloader->data, bank,
preset, sample, lokey, hikey) != 0) {
return -3;
}
fluid_synth_program_select(_synth, 0, _sfloader->id, bank, preset);
return 0;
}
int fluid_jni_remove(int samplenum, int bank, int preset)
{
if (_synth == 0) {
return -1;
}
fluid_sample_t* sample = fluid_jni_get_sample(samplenum);
if (sample == 0) {
return -2;
}
if (fluid_ramsfont_remove_izone((fluid_ramsfont_t*) _sfloader->data,
bank, preset, sample) != 0) {
return -3;
}
return 0;
}
int fluid_jni_get_sample_num()
{
for (int i = 0; i < fluid_jni_maxsamples; i++) {
if (_sample[i] == 0) {
return i;
}
}
return -1;
}
int fluid_jni_new_sample(const char* filename, int rootkey)
{
SF_INFO sfinfo;
SNDFILE* sndfile = 0;
fluid_sample_t* sample = 0;
short *data = 0;
sf_count_t count;
int err;
int num = fluid_jni_get_sample_num();
if (num < 0) {
return -1;
}
sndfile = sf_open(filename, SFM_READ, &sfinfo) ;
if (sndfile == 0) {
return -2;
}
//printf("fluid_jni_new_sample: channels=%i, srate=%i, frames=%i\n",
// sfinfo.channels, sfinfo.samplerate, sfinfo.frames);
if (sfinfo.channels != 1) {
err = -3;
goto error_recovery;
}
if (sfinfo.samplerate != 44100) {
err = -4;
goto error_recovery;
}
sample = new_fluid_ramsample();
if (sample == 0) {
err = -5;
goto error_recovery;
}
data = new short[sfinfo.frames];
if (data == 0) {
err = -6;
goto error_recovery;
}
// printf("fluid_jni_new_sample 2\n");
count = sf_readf_short(sndfile, data, sfinfo.frames);
if (count != sfinfo.frames) {
err = -7;
goto error_recovery;
}
//printf("fluid_jni_new_sample 3\n");
if (fluid_sample_set_sound_data(sample, data, sfinfo.frames, 1, rootkey) != 0) {
err = -8;
goto error_recovery;
}
//printf("fluid_jni_new_sample 4: sample=%p\n", sample);
_sample[num] = sample;
sf_close(sndfile);
delete data;
return num;
error_recovery:
if (sndfile) {
sf_close(sndfile);
}
if (sample) {
delete_fluid_ramsample(sample);
}
if (data) {
delete data;
}
return err;
}
fluid_sample_t* fluid_jni_get_sample(int num)
{
if ((num >= 0)
&& (num < fluid_jni_maxsamples)
&& (_sample[num] != 0)) {
return _sample[num];
}
return 0;
}
int fluid_jni_delete_sample(int num)
{
if ((num >= 0)
&& (num < fluid_jni_maxsamples)
&& (_sample[num] != 0)) {
delete_fluid_ramsample(_sample[num]);
_sample[num] = 0;
}
return 0;
}

View file

@ -0,0 +1,18 @@
#ifndef _FLUID_JNI_H
#define _FLUID_JNI_H
#include <fluidsynth.h>
int fluid_jni_new_synth(void);
int fluid_jni_delete_synth(int num);
int fluid_jni_add(int samplenum, int bank, int preset, int lokey, int hikey);
int fluid_jni_remove(int samplenum, int bank, int preset);
int fluid_jni_sfload(const char* filename);
int fluid_jni_new_sample(const char* filename, int rootkey);
int fluid_jni_delete_sample(int num);
int fluid_jni_get_sample_num(void);
fluid_sample_t* fluid_jni_get_sample(int num);
#endif /* _FLUID_JNI_H */