Search code examples
javajavafxaudiopcm

Dynamically producing sound in JavaFx


I want to produce a Sine wave whose amplitude and frequency can be varied dynamically. I can't use a pre-existing audio file for this. The documentation for the package media says:

In some cases the container format might simply be an elementary stream containing the encoded data.

I intend to play audio using a stream of values, which represent amplitude (pulse code modulation). This is a pseudo-code of what I am aiming for:

double frequency;
double interval; //interval between successive additions to the audio stream
double time = 0;
streamObject; //some stream object which contains amplitudes as integers in range [-128,128]

while (true){
    double value = Math.sin(time*2*Math.PI*frequency);
    streamObject.write( (int)(value*128) ); //this is some method which will append values to the end of the stream
    time += interval;
    wait(interval); //appending values in real-time because there may be changes to the frequency
}

My problem is that the only constructor for class Media takes a URI parameter. It is the same for AudioClip. I was hoping that they would take a Stream as a parameter.

Any suggestions or recommendations would be helpful.


Solution

  • There isn't a way to do what you want, currently, with JavaFX, as far as I know.

    I recommend using javax.sound.sampled.SourceDataLine for your output line. I've used this class for both a real-time theremin-like program, a real-time FM-synthesizer, and an open-source, enhanced version of Clip called AudioCue.

    The basic plan would be something like the following:

    1. Open an output line (SourceDataLine) with a given AudioFormat
    2. Generate PCM values (e.g., floats ranging from -1 to 1) that represent the desired waveform (one buffer's worth)
    3. Translate the PCM to bytes as required by the AudioFormat
    4. Write using the SourceDataLine method write
    5. Loop back to (2) for the duration of the sound