I am working on a project in which I need to get list of recording devices but If I connect new device,shows old list, Sound API takes near about 50 sec to load newly connected device list. I tried to use com.sun.media.sound.JDK13Services.setCachingPeriod() method but looks like it has been removed from jdk 1.7_0.
Is there any way to speed up the caching period?
Here is my code, Currently I have removed com.sun.media.sound.JDK13Services.setCachingPeriod() methods from code because it gives deprecation error at compile time.
private LinkedList<Mixer.Info> getTargetMixers()
{
Line.Info targetDLInfo = new Line.Info(TargetDataLine.class);
Line line = null;
LinkedList<Mixer.Info> targetMixers = new LinkedList<Mixer.Info>();
// Get all the mixers
Mixer.Info[] mixerInfoArray = AudioSystem.getMixerInfo();
for(int i=0; i<mixerInfoArray.length; i++)
{
Mixer.Info mixerInfo = mixerInfoArray[i];
try
{
Mixer mixer = AudioSystem.getMixer(mixerInfo);
if(mixer.isLineSupported(targetDLInfo))
targetMixers.add(mixerInfoArray[i]);
}
catch(Exception ex)
{
logger_.error("Error getting mixer: " + mixerInfo.getName(), ex);
}
}
return targetMixers;
}
Related
I think the title says it all. My Java program uses sound and I would like to do a check at startup rather than catch an exception. If it helps I am using FreeTTS - https://freetts.sourceforge.io/.
You can query the java AudioSystem class for available lines:
/**
* Gets a list of all audio output devices in the system
*/
public static List<Mixer> getAvailableAudioOutputDevices() {
final ArrayList<Mixer> available = new ArrayList<>();
final Mixer.Info[] devices = AudioSystem.getMixerInfo();
final Line.Info sourceInfo = new Line.Info(SourceDataLine.class);
for (int i=0; i<devices.length; ++i) {
final Mixer.Info mixerInfo = devices[i];
final Mixer mixer = AudioSystem.getMixer(mixerInfo);
if (mixer.isLineSupported(sourceInfo)) {
// the device supports output, add as suitable
available.add(mixer);
}
}
return available;
}
Do note that this does not expliclity identify sound cards, but devices that provide audio output. Thats not necessarily the same.
This error shows in Matlab under Linux whenever I try to paste a large array to matlab:
java.io.IOException: Owner failed to convert data
There is a bug report on Oracle's website and there's a workaround to it:
Fix: fix code in XSelection.java where, for incremental dataGetter.dispose() is called before validateDataGetter(dataGetter); in the method getData(long format, long time):
dataGetter.dispose();
ByteArrayOutputStream dataStream = new ByteArrayOutputStream(len);
while (true) {
WindowPropertyGetter incrDataGetter =
new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
selectionPropertyAtom,
0, MAX_LENGTH, false,
XConstants.AnyPropertyType);
try {
XToolkit.awtLock();
XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(),
incrementalTransferHandler);
propertyGetter = incrDataGetter;
try {
XlibWrapper.XDeleteProperty(XToolkit.getDisplay(),
XWindow.getXAWTRootWindow().getWindow(),
selectionPropertyAtom.getAtom());
// If the owner doesn't respond within the
// SELECTION_TIMEOUT, we terminate incremental
// transfer.
waitForSelectionNotify(incrDataGetter);
} catch (InterruptedException ie) {
break;
} finally {
propertyGetter = null;
XToolkit.removeEventDispatcher(XWindow.getXAWTRootWindow().getWindow(),
incrementalTransferHandler);
XToolkit.awtUnlock();
}
validateDataGetter(dataGetter);
However, I don't know what file to modify any java related class to matlab. Where should I look?
I'm using 320 kbps roughly 1 hour long MP3 files. The project I'm working on would seek in a collection of music inside an MP3 file so that it can shuffle the songs. I would give the timestamps to the program and it would seek to the song. It would work if JavaFX's seek method wasn't highly inaccurate.
After using MediaPlayer.seek(duration) The MediaPlayer.getCurrentTime() returns the duration we seeked to as expected. However if we listen to the mp3 file(either without seeking or in an external mp3 player) we realize that the time reported and reality is very different, sometimes even seconds.
For example MediaPlayer.seek(Duration.millis(2000)) results seeking to 0 seconds. A 2 second failure rate is not acceptable.
With WAV it seems to work. Though it does not with MP3.
The two workarounds I think so far are possible:
Writing an MP3 Decoder and Player which doesn't have the bug
Using uncompressed WAV files
Does anyone know anything better?
If anyone needs the source code there isn't much more in it:
public static void main(String[] args) {
MediaPlayer player = null;
JFXPanel fxPanel = new JFXPanel(); //To initialize JavaFX
try {
String url = new File("E:\\Music\\test.mp3").toURI().toURL().toExternalForm();
player = new MediaPlayer(new Media(url));
System.out.println("File loaded!");
} catch (MalformedURLException e) {
//e.printStackTrace();
System.out.println("Error with filename!");
System.exit(0);
}
player.play();
System.out.println("Playing!");
while (true)
{
Scanner reader = new Scanner(System.in);
String string = reader.nextLine();
if (string.equals("Exit")) System.exit(0);
else if (string.equals("Seek"))
{
player.seek(Duration.millis(2000)); //this seeks to the beggining of the file
player.pause();
try {
Thread.sleep(100); //player.getCurrentTime() doesn't update immediately
} catch (InterruptedException e) { }
System.out.println("Time: " + player.getCurrentTime().toMillis() + " / " + player.getTotalDuration().toMillis());
player.play();
}
}
}
I would recommend using the javazoom library. It is an open source java library that already has this stuff written without errors(At least none that I found).
Source
http://www.javazoom.net/index.shtml
Place your call to the seek method off the UI thread or your UI will hang.
new Thread(() ->player.seek(Duration.millis(2000))).start();
I wrote a program in Java using the pi4j lib to make sound whenever a (physical) button is clicked. This program works, but it now plays all the sounds interchangeably. I want that when you click on 2,3,4 or more buttons you only hear one sound.
This is the code I hope you can help.
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);
}
}
}
As stated in the comments, I can't give you advise regarding the AudioStream and AudioPlayer classes because I don't seem to have those in my JDK. Since my method is similar, I'll give you what I have, and you can hopefully take it from there.
Basically, the solution is to stop and/or "mute" that audio clip. This is how I accomplish it using the javax.sound package.:
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
}
}
In short, every time a pin state change event is fired, the previous audio clip will be ceased, and a new one should play. You shouldn't get any sound overlapping with this.
Also note that this is a slight modification of my original code, so let me know if there are any issues
Note about the GOTCHA
I wrote a question over on the Raspberry PI Stackexchange about an odd problem I encountered. The problem was that I discovered my audio clip would not cease playing on command. It would continue playing for a seemingly arbitrary amount of time. The stranger thing is that I only observed this while testing the app on the raspberry; it worked perfectly fine on my local machine (and even on several other machines).
It is possible my issue is related to the "looping" of my clip; if that is the case, and you simply want the clip to play for its length and no further, you may not encounter that issue, and you can probably dispense with the "muting" code I included. However, if you do observe the same issue, at least you have a solution.
Hope this helps, let me know if you have any questions.
I am now interested in changing volume of my system. I am running on Windows 8 and I found several of codes that can change "java application's" volume only. But I want to change not only my applications volume but also system's volume.
I used this but did not worked:
Mixer.Info[] infos = AudioSystem.getMixerInfo();
for (Mixer.Info info : infos) {
Mixer mixer = AudioSystem.getMixer(info);
if (mixer.isLineSupported(Port.Info.HEADPHONE)) {
Port port;
try {
port = (Port) mixer.getLine(Port.Info.HEADPHONE);
port.open();
if (port.isControlSupported(FloatControl.Type.VOLUME)) {
FloatControl bc = (FloatControl) port
.getControl(FloatControl.Type.VOLUME);
System.out.println(info);
System.out.println(" - " + bc.getValue());
bc.setValue(0.1f);
}
port.close();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
}
Thi code only changes javaw.exe's volume. For example if anyone plays youtube video on google chrome, it is impossible to change chrome's volume.
Which is the best way to control all system's volume ?
Thanks in advance.