Midi, SF2 and Synthesizer...

To make a short story long :stuck_out_tongue: 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 :slight_smile: 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)

Not mush reply (no wonder since it is very Midi/SF2 specific ;D)

I think i have find out my mistake with the pich. The fine correction is in cents not in per cent and is not on the right frequence (i wonder if the “coarse” correction is on the right one… but i didn’t come across right now)


        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];
        
        double coef = freq1/freq2*Math.pow(cents,sample.getTuneFine());
        coef = coef*sample.getScaleTuning()/100.0 + (100.0-sample.getScaleTuning())/100.0;
                
        int step = (int)(65536*coef*(double)sample.getRate()/(double)Mixer.RATE);

For attenuation, the formulat seems to be good but it didn’t seem good in the music (where did i do my mistake…)
And i still have the delay with the organ.

Tests : Organ, Midi Player

Next step, try to do the tremolo and the reverb effects.

anyone tried out the demos???

i got the same mistake i got when trying to run the JOGL online demos

Application Error “Unable to launch Application”

on both of them

JOrgan Launch File details

<?xml version="1.0" encoding="UTF-8"?> JOrgan Bonbon-Chan Organ to test MIDI Synth

exception details

com.sun.deploy.net.FailedDownloadException: Unable to load resource: http://www.bonbonchan.net/java/JFMOD.jar
at com.sun.deploy.net.DownloadEngine.actionDownload(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getResourceCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getResourceCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getResource(Unknown Source)
at com.sun.javaws.LaunchDownload.downloadJarFiles(Unknown Source)
at com.sun.javaws.LaunchDownload.downloadEagerorAll(Unknown Source)
at com.sun.javaws.Launcher.downloadResources(Unknown Source)
at com.sun.javaws.Launcher.prepareLaunchFile(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.launch(Unknown Source)
at com.sun.javaws.Main.launchApp(Unknown Source)
at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
at com.sun.javaws.Main$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Wrapped Exception details

java.util.zip.ZipException: ZIP file must have at least one entry
at java.util.zip.ZipOutputStream.finish(Unknown Source)
at java.util.zip.DeflaterOutputStream.close(Unknown Source)
at java.util.zip.ZipOutputStream.close(Unknown Source)
at com.sun.deploy.net.HttpDownloadHelper.download(Unknown Source)
at com.sun.deploy.cache.Cache.downloadResourceToTempFile(Unknown Source)
at com.sun.deploy.cache.Cache.downloadResourceToCache(Unknown Source)
at com.sun.deploy.net.DownloadEngine.actionDownload(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getResourceCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getResourceCacheEntry(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getResource(Unknown Source)
at com.sun.javaws.LaunchDownload.downloadJarFiles(Unknown Source)
at com.sun.javaws.LaunchDownload.downloadEagerorAll(Unknown Source)
at com.sun.javaws.Launcher.downloadResources(Unknown Source)
at com.sun.javaws.Launcher.prepareLaunchFile(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.launch(Unknown Source)
at com.sun.javaws.Main.launchApp(Unknown Source)
at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
at com.sun.javaws.Main$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

i dont think they are that helpfull for me to post the same details from the other demo

Street Fighter 2 is awesome. Carry on.

Hmmm it’s an one year old project :). I didn’t work on it much, I tryed to fix it yesterday but I have some problem to upload file on my server :-.

By the way, it has nothing to do with Street Fighter… I just hate when people use abbreviation for anything. It end up to have plenty of thing with the same abbreviation.

i think he was just kidding, since i posted in a “dead” topic

anyway, you dont have to make it work just for me, i am new to the forum, so i scan it, looking for something interesting and then reading about it

so if you have abandoned the project, leave it
thank you either way

The project is dead until I get back to it (I don’t know then but it will be in the next century ;)). I just have to upload a file… but the exemple use a 4mb sound bank and my connection doesn’t want me to upload it >:(. I will try again in the week.

ok then, thank you for your time

At last… it works :stuck_out_tongue:

As you can “see”, there is several problems :

  • latency in buffering process (from Java Sound)
  • some bugs in the sequencer
  • incomplet mixer (but it work not soo bad ;))