Changing volume in Java when using JLayer

余生长醉 提交于 2019-12-04 05:51:17

You may consider this an unacceptable hack, but it worked in an MP3 player I wrote. It requires a small code addition to one of the JLayer classes.

Add the following method to javazoom.jl.player.JavaSoundAudioDevice.

public void setLineGain(float gain)
{
    if (source != null)
    {
        FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
        float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());

        volControl.setValue(newGain);
    }
}

This new method then allows you to change the volume with code like this.

if (audio instanceof JavaSoundAudioDevice)
{
    JavaSoundAudioDevice jsAudio = (JavaSoundAudioDevice) audio;
    jsAudio.setLineGain(yourGainGoesHere);
}

Another (non-JLayer) way to adjust the PC's speaker volume is to use classes in the javax.sound.sampled package provided by Sun/Oracle.

On my machine, SPEAKER was the only output target supported.

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.Line.Info;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Port;

public class SoundVolumeDemo 
{

    public static void main(String[] args) 
{        
    Info source = Port.Info.SPEAKER;
    //        source = Port.Info.LINE_OUT;
    //        source = Port.Info.HEADPHONE;

        if (AudioSystem.isLineSupported(source)) 
        {
            try 
            {
                Port outline = (Port) AudioSystem.getLine(source);
                outline.open();                
                FloatControl volumeControl = (FloatControl) outline.getControl(FloatControl.Type.VOLUME);                
                System.out.println("       volume: " + volumeControl.getValue() );
                float v = 0.33F;
                volumeControl.setValue(v);
                System.out.println("   new volume: " + volumeControl.getValue() );
                v = 0.73F;
                volumeControl.setValue(v); 
                System.out.println("newest volume: " + volumeControl.getValue() );
            } 
            catch (LineUnavailableException ex) 
            {
                System.err.println("source not supported");
                ex.printStackTrace();
            }            
        }
    } 

 }

This is how I am achieving volume control in this app:

http://onebeartoe.com/media-players/randomjuke/filesystem/java-web-start/swing/index.jsp

Please note that I have only had experience with it working on MS Windows OS machines.

Bombe

Try adjusting all bands of the equalizer for the volume you’re trying to get. Maybe you can also use an EQFunction for that?

public class ChangeVolumeFunction extends EQFunction {
    public double volume = 1.0;
    public void setVolume(double volume) { this.volume = volume; }
    public float getBand(int band) { return (float) (Math.log(volume) / Math.log(2) * 6.0); }
}

I made my own version on ChrisH's answer, but instead of changing the source code of JLayer, I did it via reflection:

Class<JavaSoundAudioDevice> clazz = JavaSoundAudioDevice.class;
Field[] fields = clazz.getDeclaredFields();

try{
    SourceDataLine source = null;
        for(Field field : fields) {
            if("source".equals(field.getName())) {
                field.setAccessible(true);
                source = (SourceDataLine) field.get(device);
                field.setAccessible(false);

                FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
                if (volControl != null) {
                     float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());
                     volControl.setValue(newGain);
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Kinda crude, but it works

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!