How to capture sound from microphone with java sound API? - java

The tutorial http://download.oracle.com/javase/tutorial/sound/capturing.html
does not cover how to select microphone.
I am enumerating mixers with the following code
System.out.println("Searching for microphones");
for(Mixer.Info mixerinfo : AudioSystem.getMixerInfo()) {
mixer = AudioSystem.getMixer(mixerinfo);
//System.out.println(mixerinfo.toString());
if( mixer.isLineSupported(Port.Info.MICROPHONE) ) {
mixers.add(mixer);
System.out.println(Integer.toString(mixers.size()) + ": " + mixerinfo.toString());
}
}
i.e. by presense of microphone input. But next, having a mixer, I can't get line to read.
If I use mixer.getTargetLineInfo(), I receive an array of one Info, which when passing to mixer.getLine returns an object of type com.sun.media.sound.PortMixer$PortMixerPort, which is not ducumented.
If I use mixer.getTargetLines() I get an empty array.
If I create my own DataLine.Info and pass it to the mixer's getLine, I get unsupported exception.
So, what to do?

Left-field suggestion.
Provide a visual rendering of each sound line, in a component along the lines of the AudioPlotPanel or a simpler RMS volume. It should not take the user too long to figure which sound line they are yodeling through. ;)

I'm trying to do the same thing. I haven't quite found a good solution yet but I can tell you that's not working out because you're trying to get a DataLine from a Port mixer. If and when I figure it out I'll be sure to let you know.

Related

Validate subtitles file using vlcj (Java)

I am using an instance of vlcj DefaultEmbeddedMediaPlayer to play video. When adding subtitles to the video I want to see if the subtitle file is valid, and throw an Exception if it is not. This is my code:
File subtitlesFile = new File("subs.srt");
player.setSubTitleFile(subTitleFile);
The method setSubTitleFile(File subTitleFile) doesn't have a return value, but looking into its implementation I can see that it passes the call to libvlc, calling libvlc_video_subtitle_file(libvlc_media_player_t p_mi, String psz_subtitle), which returns 1 or 0 depending on if the subtitles have been added successfully or not. So I inherited from DefaultEmbeddedMediaPlayer and wrote my own version of that method:
public void setSubTitleFile(String subTitleFileName) {
final int status = libvlc.libvlc_video_set_subtitle_file(mediaPlayerInstance(), subTitleFileName);
System.out.println(status);
// throw Exception if status is false
}
Surprisingly this always gives me status 1, which means success. Even if I am passing an empty text file. Is this a bug? I really do not want to parse the subtitle file manually beforehand. Using the native VLC Player, I am getting an error as expected if the subtitles are invalid. Anything I could do here?
EDIT:
This is a screenshot from the native VLC player when adding an empty SRT file during play.
VLC subtitles file error
As far as I know, LibVLC/VLC is not parsing the subtitle file when you call libvlc_video_set_subtitle_file. All it is basically doing is setting a string value on some native structure that will be used later. So, you get a status of "success" because that call did its job of setting that string value.
Therefore, you will only know if the subtitle file is valid when VLC starts playing your media and it attempts to load the file at that point. Even then, I do not think you will get a specific error message - there will simply be an absence of a subtitle track.

Programatically embed a video in a slideshow using Apache Open Office API

I want to create a plugin that adds a video on the current slide in an open instance of Open Office Impress by specifying the location of the video automatically. I have successfully added shapes to the slide. But I cannot find a way to embed a video.
Using the .uno:InsertAVMedia I can take user input to choose a file and it works. How do I want to specify the location of the file programmatically?
CONCLUSION:
This is not supported by the API. Images and audio can be inserted without user intervention but videos cannot be done this way. Hope this feature is released in subsequent versions.
You requested information about an extension, even though the code you are using is quite different, using a file stream reader and POI.
If you really do want to develop an extension, then start with one of the Java samples. An example that uses Impress is https://wiki.openoffice.org/wiki/File:SDraw.zip.
Inserting videos into an Impress presentation can be difficult. First be sure you can get it to work manually. The most obvious way to do that seems to be Insert -> Media -> Audio or Video. However many people use links to files instead of actually embedding the file. See also https://ask.libreoffice.org/en/question/1898/how-to-embed-video-into-impress-presentation/.
If embedding is working for your needs and you want to automate the embedding by using an extension (which seems to be what your question is asking), then there is a dispatcher method called InsertAVMedia that does this.
I do not know offhand what the parameters are for the call. See https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=61127 for how to look up parameters for dispatcher calls.
EDIT
Here is some Basic code that inserts a video.
sub insert_video
dim document as object
dim dispatcher as object
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(document, ".uno:InsertAVMedia", "", 0, Array())
end sub
From looking at InsertAVMedia in sfx.sdi, it seems that this call does not take any parameters.
EDIT 2
Sorry but InsertVideo and InsertImage do not take parameters either. From svx.sdi it looks like the following calls take parameters of some sort: InsertGalleryPic, InsertGraphic, InsertObject, InsertPlugin, AVMediaToolBox.
However according to https://wiki.openoffice.org/wiki/Documentation/OOoAuthors_User_Manual/Getting_Started/Sometimes_the_macro_recorder_fails, it is not possible to specify a file for InsertObject. That documentation also mentions that you never know what will work until you try it.
InsertGraphic takes a FileName parameter, so I would think that should work.
It is possible to add an XPlayer on the current slide. It looks like this will allow you to play a video, and you can specify the file's URL automatically.
Here is an example using createPlayer: https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=57699.
EDIT:
This Basic code works on my system. To play the video, simply call the routine.
sub play_video
If Video_flag = 0 Then
video =converttoURL( _
"C:\Users\JimStandard\Downloads\H264_test1_Talkinghead_avi_480x360.avi")
Video_flag = 1
'for windows:
oManager = CreateUnoService("com.sun.star.media.Manager_DirectX")
' for Linux
' oManager = CreateUnoService("com.sun.star.media.Manager_GStreamer")
oPlayer = oManager.createPlayer( video )
' oPlayer.CreatePlayerwindow(array()) ' crashes?
'oPlayer.setRate(1.1)
oPlayer.setPlaybackLoop(False)
oPlayer.setMediaTime(0.0)
oPlayer.setVolumeDB(GetSoundVolume())
oPlayer.start() ' Lecture
Player_flag = 1
Else
oPlayer.start() ' Lecture
Player_flag = 1
End If
End Sub

Change Mixer to output sound to in java

I am trying to play a wav/mp3 to my virtual audio cable, I have been searching for hours but can't seem to find how to achieve this. I have been able to play sound in both formats but I can't get it to output to 'Line-1' rather than 'Speakers'
Any helpful links or example code would be greatly appreciated.
To get an array of all Mixers on the current platform, you may use AudioSystem#getMixerInfo:
static void printAllMixerNames() {
for(Mixer.Info info : AudioSystem.getMixerInfo()) {
System.out.println(info.getName());
}
}
If your virtual cable is available, it will be in the array. For example, on my Mac the following is printed:
Java Sound Audio Engine
Built-in Input
Soundflower (2ch)
Soundflower (64ch)
Pro Tools Aggregate I/O
(Soundflower is a virtual device.)
To get some specific Mixer you unfortunately need to do String evaluation. So you need to discover its name, vendor, whatever, beforehand or give the user an option to pick one from a list.
static Mixer getMixerByName(String toFind) {
for(Mixer.Info info : AudioSystem.getMixerInfo()) {
if(toFind.equals(info.getName())) {
return AudioSystem.getMixer(info);
}
}
return null;
}
Once you have a particular Mixer you can obtain a Line or AudioInputStream from it. You can obtain a Clip from it through AudioSystem#getClip(Mixer.Info).
I am trying to play a wav/mp3...
javax.sound.sampled does not support mp3. Alternatives can be found here.

How to do you get output from Javascript into Java using ScriptEngine

With this simple piece of applescript I can list the names of all songs within iTunes
tell application "iTunes"
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
try
name of nexttrack
end try
end repeat
end tell
I then run it as Java 7 code using ScriptEngine, however it is only obvious how to get the result of the script which in this case is the name of the last track only.
StringBuilder script =new StringBuilder();
script.append("tell application \"iTunes\"\n");
script.append("set mainLibrary to library playlist 1\n");
script.append("repeat with nexttrack in (get every track of mainLibrary)\n");
script.append("try\n");
script.append("name of nexttrack\n");
script.append("end try\n");
script.append("end repeat\n");
script.append("end tell\n");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
System.out.println(engine.eval(script.toString()));
How do can I capture the name of all tracks , i.e all output from the script. I assume I have to redirect standard out to a Reader, but cannot see how to do it.
Update:
I found this article
http://www.informit.com/articles/article.aspx?p=696621&seqNum=6
But updating by code to
StringBuilder script =new StringBuilder();
script.append("tell application \"iTunes\"\n");
script.append("set mainLibrary to library playlist 1\n");
script.append("repeat with nexttrack in (get every track of mainLibrary)\n");
script.append("try\n");
script.append("name of nexttrack\n");
script.append("end try\n");
script.append("end repeat\n");
script.append("end tell\n");
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("AppleScript");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
StringWriter swError = new StringWriter();
PrintWriter pwError = new PrintWriter(swError);
engine.getContext().setWriter(pw);
engine.getContext().setErrorWriter(pwError);
System.out.println(engine.eval(script.toString()));
System.out.println("************* engine:"+sw.getBuffer());
System.out.println("************* engine error:"+swError.getBuffer());
Just outputs
See You on the Other Side (short)
************* engine:
************* engine error:
So you can clearly see the script works as the eval shows the name of the last track , but I'm getting nothing back from the redirected writers. Wondering does this actually work for applescript ?
Update 2
I wrote a test in Javascript and found setting the writers DID WORK for that so Im thinking that either
There is something broken in script engine for Applescript ( Im using a recent build 1.7.0_40-ea-b29) of the early access version of Java 7 on OSX)
My Applescript is wrong, i.e rather than just name of nexttrack I should be doing something like echo name of nexttrack to actually make it go to to stdout.
I'd like to think (2) was the problem, but I canot find any reference to outputting text in Applescript, echo is not a valid command and the print command does actually try to print to a printer rather than print to stdout as it would in Java or C.
Update 3
So I couldn't get this working, and now wondering if Applescript only ever writes the return value. I found an example of using stdout ( or so i thought) but I think that was just a naming convention, and in fact all it does is continually append data to a variable, and eventually return that.
So I did it get something working by using the following script stored in a file, and then used in Java with engine.eval(new java.io.FileReader("filename")
tell application "iTunes"
set output to ""
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
if (class of nexttrack is file track) then
try
set trackname to name of nexttrack
set loc to location of nexttrack
set locpath to POSIX path of loc
set persistid to persistent ID of nexttrack
set nextline to trackname & "::" & locpath & "::" & persistid
set output to output & "\n" & nextline
end try
end if
end repeat
copy output to stdout
end tell
but this doesnt actually resolve the original question, and the one problem with it is that if there is any error then I wont get anything back, whereas if it failed halfway through reading my iTuneslibrary and I was using stdout I would at least get half the data back.
To answer you original question, you get back whatever you "return" at the end of the script. If you do not have a specific "return" statement then by default you get back the result from the last action (which in your case is the last iteration of the repeat loop). Therefore if you need more than the last action returned you must create the return value in your script and then return it at the end.
but this doesnt actually resolve the original question, and the one
problem with it is that if there is any error then I wont get anything
back, whereas if it failed halfway through reading my iTuneslibrary
and I was using stdout I would at least get half the data back.
This is incorrect. The try block around your code will make applescript ignore the errors and continue, so anything you collect that doesn't error will still get returned.
Note that you have some errors in your latest applescript code. Especially this line makes no sense as applescript doesn't know what stdout is. So your comment is incorrect.
copy output to stdout
Here's what you need to do. As mentioned, you use "return" to return something. So I cleaned up your code. This will put each line of the repeat loop on a separate line of the output variable, which you return at the end of your code, which you can then parse once you bring it into your javascript code. Try this...
tell application "iTunes"
set output to ""
set mainLibrary to library playlist 1
repeat with nexttrack in (get every track of mainLibrary)
if (class of nexttrack is file track) then
try
set trackname to name of nexttrack
set loc to location of nexttrack
set locpath to POSIX path of loc
set persistid to (persistent ID of nexttrack) as text
set nextline to trackname & "::" & locpath & "::" & persistid & return
set output to output & nextline
end try
end if
end repeat
end tell
return output

How do you list all available (input) ports using javax.sound.sampled.*?

According to my research, Java's sound api does not play well with OsX. It has a hard time determining the active input, so it generally defaults to the first system input.
My solution is to iterate through an array of input ports, recording a couple milliseconds of audio and comparing those pieces. Whichever one has the greatest amplitude, I'll use as my input.
My question is, what would the best method be for generating an array of all input ports available to Java?
You can list all of the available Mixer objects using the following:
Mixer.Info[] mixers = AudioSystem.getMixerInfo();
for (Mixer.Info mixerInfo : mixers){
System.out.println(mixerInfo);
}
On my system, a Mac, this is the result:
Java Sound Audio Engine, version 1.0
Built-in Input, version Unknown Version
Built-in Microphone, version Unknown Version
Edit
Here's how to extract a list of valid Target lines that you can get audio input from:
Mixer.Info[] mixers = AudioSystem.getMixerInfo();
List<Line.Info> availableLines = new ArrayList<Line.Info>();
for (Mixer.Info mixerInfo : mixers){
System.out.println("Found Mixer: " + mixerInfo);
Mixer m = AudioSystem.getMixer(mixerInfo);
Line.Info[] lines = m.getTargetLineInfo();
for (Line.Info li : lines){
System.out.println("Found target line: " + li);
try {
m.open();
availableLines.add(li);
} catch (LineUnavailableException e){
System.out.println("Line unavailable.");
}
}
}
System.out.println("Available lines: " + availableLines);
Once you have the Line.Info object, you can get the TargetDataLine associated with the Line.Info object by calling AudioSystem.getLine() and using that Line.Info as a parameter.
Basics on how to determine what resources are available can be found here:
Accessing Audio System Resources
I found this section to be the most helpful in terms of example code, in the Java Sound tutorials:
http://download.oracle.com/javase/tutorial/sound/converters.html

Categories

Resources