To make a short story long There is all the story.
I was looking solution for the background music (mp3, ogg, midi…). But i was a bit disappointed by the quality of the midi sound.
Since it is possible to use “soundbank”, i look for a new one (and tool to manage them). I find out a new sound bank but it was the same quality (the “delux” version…) and i never find anything on the file format or on tools for them ???
After some search, i find out that the most popular (and open) sound font (why did they call it sound bank in java is the SF2 (you can easily fond a lot of them ;D). Then I try to create my own SoundBank class to use with current Midi API… not much luck. I down load the jdk source code to see how they deal with it… I didn’t get it at all :-\ (allmost all methods are “native” and I didn’t find the C code)
“Hooo well, I will remake all in a 100% java code. It musn’t be that difficult” (Dreaming dreaming ;D)
So I get the file reference. I make a loader (only 60 parameters per sample :o). I make a sequencer, a synthesizer, a mixer (the most basic one). First trys, a lovely silence. Second trys, i heard a magic noise. Third ones, the samples !!! :). Victory ! I play a midi file and i heard one of the most horrible (and hilarious) music ever :P. I have make some amelioration on the mixer but i have still have lots of problem.
Loading sample :
ByteBuffer buff = ByteBuffer.allocate((int)size+1);
if (buff == null) { throw(new JFMODException("Not enough memory")); }
int position = 1;
while (size >0)
{
int read = is.read(buff.array(),position,(int)size);
size -= read;
position += read;
}
memoryDump = buff.asShortBuffer();
There are signed 16 bit data. I’m not sur of the convertion byte -> short (it was working for me… until I try to use webstart and i have to change it (0->1 in position :o)).
Attenuation :
public static int centibelToPercent(int c)
{
c = toShort(c);
if (c<0){ return 0; }
double percent = DAHDSR.MAX_VOLUME / (Math.exp(c/200.0)/Math.log(10));
return (int)percent;
}
All attenuation are given in decibel (in centibel in fact). Is it the good formulat ? I didn’t find a good way to apply it to the envelope
Pitch :
double freq1 = freq[note];
int tone = sample.getRootKey()+sample.getTuneCoarse();
if (tone<0) { tone = 0; } else if (tone>128) { tone = 128; }
double freq2 = freq[tone]*(100.0+sample.getTuneFine())/100.0;
int step = (int)(65536*freq1/freq2*(float)sample.getRate()/(float)Mixer.RATE);
It work for some samples, and it didn’t for some others… (there is the scaleTuning parameter to add to this, i’m not sure how to deal with it)
DAHDSR :
Delay, Attack, Hold, Decay, Sustain, Release (not less…)
I’m not sur : I play the delay,attack,hold, decay, sustain while the note is on. If the note turn off, i drop the envelope value from where it is to 0 in the release time. (it seems strange for a harp to have a 10s release ???). May be I should use a fixe step rather than a fixe time.
Delay :
When i start playing a instrument, there is a delay at the begining (it seem to come from java sound). Any way to deal with it ? (it is not that important for a music)
I have made an organ to test the samples. (qsdfghjklm for notes, 1234567890 for octave)