简体   繁体   中英

Javax Sound Sampled: Unsupported Control Type issues with FloatType.Control

I am having trouble added control types to a clip in the java sampled package. Please see the below code as a reference.

I have made sure to call clip.open() before adding a control to the clip and I still have the same issue. I have tried to print out all available controls for a clip and I find that I have no controls available to me. Strangely, this works on other peoples machine but I am having trouble on mine. It is not recognising any of the FloatControl.Type's that are available such as MasterGain, Volume etc.

I have tried to downgrade from JDK 9 to 8 as my friend has 8. Java 7 is that last JDK to have no issue with JavaSound however I am baffled to why is works on other peoples machines. I know that I am not running things concurrently with Threads at the moment and the code needs refactoring. Any advice SPECIFIC to my problem is appreciated.

The gain/volume is being controlled by a JSlider in another class and this works fine when printing out the values using a changelistener. (CODE IN QUESTION IS AT THE VERY BOTTOM OF MY CODE SNIPPET)

public class AudioEngine {

    private FileManager filemanager;
    private File sound;
    private Clip clip;
    private ArrayList<File> files;
    private ArrayList<Clip> clips;
    private DataLine.Info[] lines;
    private ArrayList<AudioInputStream> streams;
    private long trackposition; // positioning of current clip to determine where in a track our play back starts from.
    private Mixer mixer;   // main mixer
    private boolean playtrigger;

    public AudioEngine() {

        filemanager = new FileManager();

        trackposition = 0;    // set initial playback to beginning of track unless it is paused....

        playtrigger = true;

        Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();     // get I/O devices for set up
        for (Mixer.Info info : mixInfos) {
            System.out.println(info.getName() + " --------- " + info.getDescription());
        }


        mixer = AudioSystem.getMixer(mixInfos[0]);

        Line[] lines = mixer.getSourceLines();


    }

    /**
     * Set up the Mixer with multiple data lines, input streams, files and clips.
     */

    public void mixerSetUp(JComboBox<String> list, ArrayList<String> tracklist) throws Exception {

        files = new ArrayList<>();
        streams = new ArrayList<>();
        clips = new ArrayList<>();
        lines = new DataLine.Info[tracklist.size()];

        for (int i = 0; i < tracklist.size(); i++) {
            files.add(new File(tracklist.get(i)));
            streams.add(AudioSystem.getAudioInputStream(files.get(i)));
            lines[i] = new DataLine.Info(Clip.class, streams.get(i).getFormat());
            clips.add((Clip) AudioSystem.getLine(lines[i]));
            clips.get(i).open(streams.get(i));

        }

        System.out.println("mixer lines: " + lines.length);
        System.out.println(files.size());
        System.out.println(streams.size());
        System.out.println(clips.size());
        System.out.println(lines.length);

        Line line = mixer.getLine(lines[0]);

       Control [] controls = line.getControls();
       System.out.println(controls.length);
       for(Control control: controls) {
           System.out.println(control);
       }

    }

    /**
     * Converts our .WAV file in to an audio stream. Then we convert stream into a clip for playback.
     *
     * @param list      Our track list displayed in JComboBox (shortened version of full file path).
     * @param tracklist Our list of tracks with their full path. Plays as a Clip if selected.
     * @throws IOException
     * @throws UnsupportedAudioFileException
     * @throws LineUnavailableException
     * @throws Exception                     - More generic as all 3 of the above exceptions would have need to be thrown.
     */


    public void play(JComboBox<String> list, ArrayList<String> tracklist) throws LineUnavailableException {

        // PRESS LOAD TRACKS EVERY TIME A NEW TRACK IS ADDED

        for (Clip clip : clips) {
            if (clip != null) {
                System.out.println("Start Running");
                clip.setMicrosecondPosition(trackposition);
                clip.start();

            }
        }

    }

    /**
     * If track is running, stop the clip and set track positioning back to 0.
     */

    public void stop() {

        for (Clip clip : clips) {
            if (clip.isRunning()) {
                clip.stop();
                trackposition = 0;
            }
        }

    }

    /**
     * Set the track position when the pause button is pressed. Play back will continue from this set position once
     * user presses Play button. Track position will be set to 0 once user stops the track.
     */

    public void pause() {

        for (Clip clip : clips) {

            trackposition = clip.getMicrosecondPosition();
            clip.stop();
        }

    }

    /**
     * Iterates through all of the tracks and sets volume to value specified in parameter
     * @param value The volume for the tracks to be set to.
     */

    public void adjustVolume(int value) throws LineUnavailableException {


        if (clips != null) {
            for (Clip clip : clips) {
                FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                gainControl.setValue((float)value);
            }
        }
    }


}

The presence or lack of a Control varies with computer and OS. You can test whether a control is supported or not with isControlSupported

Even when controls are supported (hit or miss), they are often inadequately implemented for higher-end real time purposes. For example, they may only pass on changes at buffer boundaries, which can lead to zippering effects or other discontinuities if you are trying to do real-time mixing.

You may need to either code your own volume changes (using access into sound data provided by SourceDataLine) or make use of a public library that does this. For example, AudioCue was written to behave like a Clip, but implements real-time volume, panning and frequency changes. The code is on github (opensource) and will also let you inspect how to implement this if you decide to roll your own.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM