禁用java中的其他声音

时间:2014-04-23 15:28:54

标签: java raspberry-pi javasound audio

我用Java编写了一个程序,使用pi4j lib在点击(物理)按钮时发出声音。这个程序有效,但它现在可以互换地播放所有声音。我希望当你点击2,3,4或更多按钮时,你只能听到一个声音。

这是我希望你可以帮助的代码。

public class ButtonSoundsProject{
public static void main(String args[]) throws InterruptedException {
    System.out.println("Toy has been started!");

    // create gpio controller
    final GpioController gpio = GpioFactory.getInstance();

    // provision gpio pin #02 as an input pin with its internal pull down resistor enabled
    GpioPinDigitalInput[] pins = {
        gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_DOWN),
        gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_DOWN),
        gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN),
        gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, PinPullResistance.PULL_DOWN),
        gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, PinPullResistance.PULL_DOWN),
        gpio.provisionDigitalInputPin(RaspiPin.GPIO_05, PinPullResistance.PULL_DOWN),};

    final ArrayList<String> soundList = new ArrayList<String>();
    soundList.add("/home/pi/Sounds/Sound1.wav");
    soundList.add("/home/pi/Sounds/Sound2.wav");
    soundList.add("/home/pi/Sounds/Sound3.wav");
    soundList.add("/home/pi/Sounds/Sound4.wav");
    soundList.add("/home/pi/Sounds/Sound5.wav");
    soundList.add("/home/pi/Sounds/Sound6.wav");
    soundList.add("/home/pi/Sounds/Sound7.wav");
    soundList.add("/home/pi/Sounds/Sound8.wav");
    soundList.add("/home/pi/Sounds/Sound9.wav");
    soundList.add("/home/pi/Sounds/Sound10.wav");
    soundList.add("/home/pi/Sounds/Sound11.wav");
    soundList.add("/home/pi/Sounds/Sound12.wav");


    // create and register gpio pin listener
    GpioPinListenerDigital listener = new GpioPinListenerDigital() {
        @Override
        public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
            // display pin state on console

            final int randomNum = 0 + (int) (Math.random() * 12);
            System.out.println(randomNum);

            System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
            InputStream in;
            try {
                System.out.println(soundList.get(randomNum).toString());
                String filepath = soundList.get(randomNum).toString();
                in = new FileInputStream(new File(filepath));
                AudioStream as = new AudioStream(in);
                AudioPlayer.player.start(as);

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    };

    gpio.addListener(listener, pins);


    for (;;) {
        Thread.sleep(500);
    }
}

}    

1 个答案:

答案 0 :(得分:0)

正如评论中所述,我无法就AudioStreamAudioPlayer类提供建议,因为我似乎没有JDK中的那些。由于我的方法类似,我会给你我所拥有的,你可以从那里拿走它。

基本上,解决方案是停止和/或“静音”该音频剪辑。这就是我使用javax.sound包完成它的方式。:

private Clip currentAudioClip; // Keep a reference to the current clip being played

public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {

    // Call this every time regardless.
    // If nothing is playing, this will do nothing.
    stopAudio();

    String filepath = soundList.get(randomNum)
    URL soundFileUrl = new File(filePath).toURI().toURL();

    AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFileUrl);

    Line.Info lineInfo = new Line.Info(Clip.class);
    Line line = AudioSystem.getLine(lineInfo);

    currentAudioClip = (Clip) line;
    currentAudioClip.open(audioInputStream);
    audioClip.start();

    // Alternative if you want to loop continuously. Comment out the `.start` line to use this.
    // audioClip.loop(Clip.LOOP_CONTINUOUSLY);
}

public void stopAudio(){
    if(audioClip != null){
        muteLine(); // A gotcha I discovered (see explanation below)
        audioClip.stop();

        // audioClip.loop(0); // if you chose to loop, use this instead of `.stop()`
        audioClip.flush();
        audioClip = null;
    }
}

public void muteLine(){
    BooleanControl muteControl = (BooleanControl) audioClip.getControl(BooleanControl.Type.MUTE);
    if(muteControl != null){
        muteControl.setValue(true); // True to mute the line, false to unmute
    }       
}

简而言之,每次触发引脚状态更改事件时,前一个音频剪辑都将停止,并且应该播放一个新的音频剪辑。你不应该与此重叠。

另请注意,这是对我原始代码的略微修改,请告知我是否存在任何问题

关于GOTCHA的说明

我在a question上写了Raspberry PI Stackexchange关于我遇到的奇怪问题。问题是我发现我的音频片段不会停止播放命令。它会继续玩一段看似随意的时间。更奇怪的是,我只在测试覆盆子上的应用程序时观察到了这一点;它在我的本地机器上工作得很好(甚至在其他几台机器上也是如此)。

我的问题可能与我剪辑的“循环”有关;如果是这种情况,并且您只是希望剪辑播放其长度而不再进行播放,则可能不会遇到该问题,并且您可以省去我所包含的“静音”代码。但是,如果你确实观察到同样的问题,至少你有一个解决方案。

希望这有帮助,如果您有任何问题,请与我联系。