[Audio-engine-dev] Gervill 0.2

Karl Helgason kalli at midverk.is
Sun Oct 14 17:28:13 PDT 2007


Hi Alex,

Here are my answer to your notes.

3. (multi-recevers implementation).
You are correct about his one, I'll fix it.

4.
WaveFloatFileReader is used to provide support
for Wave file in FLOAT format. It was supposed to be
register as AudioFileReader in /META-INF/services
(Which i forgot to do in current release of Gervill).

5.
LargeSoundbankReader is used to provide
support for loading SoundBanks in large mode
e.g. where sample data is not loaded into memory.

I use it to load large piano soundfont (about 500mb)
and Sonivox 250 Meg GM Wavetable soundfont
(from http://www.sonivoxmi.com).

You can see similar idea in javax.swing.JTree
where they have the method: setLargeModel(boolean newValue).

This is probably not the best way to do it.
Ideally we would have
  getSoundbank(File file, boolean largeModel)
In javax.sound.midi.MidiSystem.

Having LargeModel support is also useful when we
want to use big audio files as soundbank.
For example If we have any pre-recorded audio file
which we want to play along some midi sequence file.

2.
I don't think providing simple Mixer is good enough.
The reason for the Mixer interface was to provide
support for reading audio from synthesizer in pull mode
(where user pulls data from the synthesizer
instead of it being pushed thru Mixer/SourceDataLine).
In example below I suggest we add this method instead:

  public AudioInputStream openStream(AudioFormat targetFormat)

Which is much simpler and more intuitive way than using Mixer interface.
And it can also be writed directly to Wave file using:
 AudioSystem.write(AudioInputStream stream, AudioFileFormat.Type fileType, File out)

1.
I propose a AudioSynthesizer interface.
A synthesizer that push audio into SourceDataLine
or provides audio where user pulls it from AudioInputStream.

When the synthesizer is in push mode, a special
audio feeder thread is created which push data into
specified SourceDataLine or system default Mixer.
The reason I choose to use SourceDataLine is because
it includes information about audio format and buffer size to use.
Therefore user don't have to specify format and latency
(already provided with line.getFormat() and line.getBufferSize() methods.)

No audio feeder thread is needed when synthesizer
is in pull mode. This is suitable when
rendering audio in non-real time mode.
Sequencer object can't used with synthesizer in this mode.

I also suggest to add "properties" for advanced functionality.
Similar like we do in java.sql.Driver, where we have getPropertyInfo
method which provide information about possible properties.
With that method we can make restriction to properties like "resamplerType".


Here is a brief example how the synthesizer is used in pull mode:
-----------------------------------------------------------------

/*
 * Open synthesizer in pull mode in the format 96000hz 24 bit stereo
 * using Sinc interpolation for highest quality.
 * With 1024 in max polyphony.
 */
AudioFormat format = new AudioFormat(96000, 24, 2, true, false);
AudioSynthesizer synthesizer = MidiSyster.getSynthesizer();
Map<String,Object> info = new HashMap<String,Object>();
info.put("resampletType", "sinc");
info.put("maxPolyphony", "1024");
AudioInputStream stream = synthesizer.openStream(format, info);

/*
 * Play midi note 60 on channel 1 for 1 sec.
 */
Receiver recv = synthesize.getReceiver();
msg.setMessage(msg.NOTE_ON, 0, 60, 80);
recv.send(msg, 0);
msg.setMessage(msg.NOTE_ON, 0, 60, 80);
recv.send(msg, 1000000);

/*
 * Calculate how many bytes 10 seconds are.
 */
long len = (long)(format.getFrameSize() * format.getFrameRate() * 10);

/*
 * Write 10 second into output file.
 */
stream = new AudioInputStream(stream, format, len);
AudioSystem.write(stream, AudioFileFormat.Type.WAVE, new File("output.wav"));

/*
 * Close all resources.
 */
recv.close();
stream.close();
synthesizer.close();



------------------------------------------------------------

classe SynthesizerPropertyInfo {

  /*
   * Array of possible values for the field
   * SynthesizerPropertyInfo.value.
   *
   */
  Object[] choices;

  /*
   * A brief description of the property, which may be null.
   *
   */
  String description;

  /*
   * The name of the property.
   *
   */
  String name;

  /*
   * Default value used by synthesizer if not specified.
   *
   */
  Object value;

  /*
   *  Obtains the class used in the value field.
   *
   */
  Class valueClass;

}


interface AudioSynthesizer extends Synthesizer {

  /*
   * Gets information about the possible
   * properties for this synthesizer.
   *
   */
  SynthesizerPropertyInfo[] getPropertyInfo();

  /*
   * Open device in push mode (e.g. AudioSynthesize
   * is responsible to render and write it's data
   * to SourceDataLine).
   * If line is not specified then system default mixer and line
   * is used.
   *
   * Additional parameters can be set through info parameter.
   * To query what parameter are available use getPropertyInfo method.
   *
   */
  public void open(SourceDataLine line, Map<String,Object> info);

  /*
   * Open device in push mode (e.g. AudioSynthesize
   * is responsible to render and write it's data
   * to SourceDataLine).
   * If line is not specified then system default mixer and line
   * is used.
   *
   */
  public void open(SourceDataLine line);

  /*
   * Opens device in pull mode, e.g. audio data is rendered
   * user calls read in AudioInputStream.
   * This is suitable when user wants to render midi data
   * non-realtime.
   *
   * Additional parameters can be set through info parameter.
   * To query what parameter are available use getPropertyInfo method.
   *
   */
  public AudioInputStream openStream(AudioFormat targetFormat, Map<String,Object> info);

  /*
   * Opens device in pull mode, e.g. audio data is rendered
   * user calls read in AudioInputStream.
   * This is suitable when user wants to render midi data
   * in non-real time.
   *
   */
  public AudioInputStream openStream(AudioFormat targetFormat) ;

}



More information about the audio-engine-dev mailing list