我用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);
}
}
}
答案 0 :(得分:0)
正如评论中所述,我无法就AudioStream
和AudioPlayer
类提供建议,因为我似乎没有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关于我遇到的奇怪问题。问题是我发现我的音频片段不会停止播放命令。它会继续玩一段看似随意的时间。更奇怪的是,我只在测试覆盆子上的应用程序时观察到了这一点;它在我的本地机器上工作得很好(甚至在其他几台机器上也是如此)。
我的问题可能与我剪辑的“循环”有关;如果是这种情况,并且您只是希望剪辑播放其长度而不再进行播放,则可能不会遇到该问题,并且您可以省去我所包含的“静音”代码。但是,如果你确实观察到同样的问题,至少你有一个解决方案。
希望这有帮助,如果您有任何问题,请与我联系。