Procedural music

Hi ;D

The Java4k seems to getting start and so I. This year, I really want to try to put some music in my game.
Midi synthetizer seems to be a good choise since there is everything that I need and you only need a few line of code :


     synth = MidiSystem.getSynthesizer();
     synth.open();
     synth.getChannels()[0].programChange(XX);

     ...

    synth.getChannels()[0].allNotesOff();
    synth.getChannels()[0].noteOn( XX,YY);

Now my problem is the music data. I don’t think I can store raw data like that (it will take too much space). So I want to use an algorithm to produce procedural music. But I’m not use to those sort of things (and I’m no good at music :P).

While googling, I found some interresting site :
Fractal melody
Fractal Music
Tune Toys (I have play a lot with the exemples ;D)

Even so I didn’t manage to do anything good (in a small size). Does anyone have some expercience in this field ?

Not much luck on this suject…

I have another problem related to this. I use the Synthetizer class to deal with the MIDI ouput. But not all device have one. I have found that a Synthetizer can be faked with a Receiver :


import java.util.List;
import javax.sound.midi.Instrument;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiDevice.Info;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Patch;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Transmitter;
import javax.sound.midi.VoiceStatus;

/**
 *
 * @author
 */
public class GenericSynthetizer implements Synthesizer
{
  protected MidiDevice device;
  protected GenericMidiChannel channels[];

  public GenericSynthetizer(MidiDevice device) throws MidiUnavailableException
  {
    this.device = device;

    device.open();

    try
    {
      ShortMessage message = new ShortMessage();
      message.setMessage(ShortMessage.START);
      device.getReceiver().send(message,0);
    }
    catch (InvalidMidiDataException ex)
    {
      ex.printStackTrace();
    }

    channels = new GenericMidiChannel[16];
    for(int i=0;i<16;i++)
    {
      channels[i] = new GenericMidiChannel(i,device,device.getReceiver());
    }
  }

  public int getMaxPolyphony()
  {
    return 16;
  }

  public long getLatency()
  {
    return 0;
  }

  public MidiChannel[] getChannels()
  {
    return channels;
  }

  public VoiceStatus[] getVoiceStatus()
  {
    return null;
  }

  public boolean isSoundbankSupported(Soundbank soundbank)
  {
    return false;
  }

  public boolean loadInstrument(Instrument instrument)
  {
    return true;
  }

  public void unloadInstrument(Instrument instrument)
  {
    
  }

  public boolean remapInstrument(Instrument from, Instrument to)
  {
    return true;
  }

  public Soundbank getDefaultSoundbank()
  {
    return null;
  }

  public Instrument[] getAvailableInstruments()
  {
    return null;
  }

  public Instrument[] getLoadedInstruments()
  {
    return null;
  }

  public boolean loadAllInstruments(Soundbank soundbank)
  {
    return true;
  }

  public void unloadAllInstruments(Soundbank soundbank)
  {
     
  }

  public boolean loadInstruments(Soundbank soundbank, Patch[] patchList)
  {
    return true;
  }

  public void unloadInstruments(Soundbank soundbank, Patch[] patchList)
  {

  }

  public Info getDeviceInfo()
  {
    return device.getDeviceInfo();
  }

  public void open() throws MidiUnavailableException
  {
    device.open();
  }

  public void close()
  {
    device.close();
  }

  public boolean isOpen()
  {
    return device.isOpen();
  }

  public long getMicrosecondPosition()
  {
    return device.getMicrosecondPosition();
  }

  public int getMaxReceivers()
  {
    return device.getMaxReceivers();
  }

  public int getMaxTransmitters()
  {
    return device.getMaxTransmitters();
  }

  public Receiver getReceiver() throws MidiUnavailableException
  {
    return device.getReceiver();
  }

  public List<Receiver> getReceivers()
  {
    return device.getReceivers();
  }

  public Transmitter getTransmitter() throws MidiUnavailableException
  {
    return device.getTransmitter();
  }

  public List<Transmitter> getTransmitters()
  {
    return device.getTransmitters();
  }

}


import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;

/**
 *
 * @author 
 */
public class GenericMidiChannel implements MidiChannel
{
  protected MidiDevice device;
  protected Receiver receiver;
  protected int nb;
  protected ShortMessage message;

  public GenericMidiChannel(int nb,MidiDevice device,Receiver receiver)
  {
    this.nb = nb;
    this.device = device;
    this.receiver = receiver;

    message = new ShortMessage();
  }

  public void noteOn(int noteNumber, int velocity)
  {
    try
    {
      message.setMessage(ShortMessage.NOTE_ON, nb, noteNumber, velocity);
      receiver.send(message, 0);
    }
    catch (InvalidMidiDataException ex)
    {
      ex.printStackTrace();
    }
  }

  public void noteOff(int noteNumber, int velocity)
  {
    try
    {
      message.setMessage(ShortMessage.NOTE_OFF, nb, noteNumber, velocity);
      receiver.send(message, 0);
    }
    catch (InvalidMidiDataException ex)
    {
      ex.printStackTrace();
    }
  }

  public void noteOff(int noteNumber)
  {

  }

  public void setPolyPressure(int noteNumber, int pressure)
  {
       throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getPolyPressure(int noteNumber)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setChannelPressure(int pressure)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getChannelPressure()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void controlChange(int controller, int value)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getController(int controller)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void programChange(int program)
  {
    try
    {
      message.setMessage(ShortMessage.PROGRAM_CHANGE, nb, program, 0);
      receiver.send(message,0);
    }
    catch (InvalidMidiDataException ex)
    {
      ex.printStackTrace();
    }
  }

  public void programChange(int bank, int program)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getProgram()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setPitchBend(int bend)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getPitchBend()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void resetAllControllers()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void allNotesOff()
  {
    try
    {
      message.setMessage(ShortMessage.CONTROL_CHANGE, nb, 123, 0);
      receiver.send(message, 0);
    }
    catch (InvalidMidiDataException ex)
    {
      ex.printStackTrace();
    }
  }

  public void allSoundOff()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean localControl(boolean on)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setMono(boolean on)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean getMono()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setOmni(boolean on)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean getOmni()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setMute(boolean mute)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean getMute()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public void setSolo(boolean soloState)
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean getSolo()
  {
        throw new UnsupportedOperationException("Not supported yet.");
  }
}

Until now, I only use noteOn, noteOff, programChange and allNoteOff. It’s work with the Java Sound Synthetizer and with the Microsoft wave table but it doesn’t with the Timidity driver (whish is the one that I want to use ofcourse :-).
I don’t get any error, there is just no sound.

Any idea ? ???

Unless the rules have changed since last year:

[quote]No soundbanks may be used because they are not a default part of the “public” JRE. You will have to create your sounds at runtime rather than use MIDIs.
[/quote]

Arf… thanks :(. Even so, I still work on it (It became a full “project” by itself). For the 4k, I will see with basic sin sound but I don’t know if I will have enough bytes left.

It really annoy me to not be able to use Timidity driver :’(.