Java Forum / General / August 2007
Java Audio Help (Mixers and Ports)
KWhat4 - 11 Aug 2007 23:56 GMT I have manged to get a port on a selected mixer for audio capture however I am unable to get a SourceDataLine for writing audio to the speakers. The following is how I am attempting to do it but i am getting a class cast exception (cant go from Line to SourceDataLine). Any Ideas?
//Port.Info objPort; objOutputDataLine = (SourceDataLine) objMixer.getLine(objPort);
Andrew Thompson - 12 Aug 2007 00:55 GMT ...
>Any Ideas? Post code* rather than..
>objOutputDataLine = (SourceDataLine) objMixer.getLine(objPort); ..vague snippets.
And by 'code' I mean a specific form, an SSCCE. <http://www.physci.org/codes/sscce.html>
I am not sure it will help you, but here is a small sound based tool I wrote to plot the sound traces on-screen, an oscilloscope. <http://www.physci.org/test/oscilloscope/AudioTrace.java>
It's homepage is here.. <http://www.physci.org/sound/audiotrace.html>
 Signature Andrew Thompson http://www.athompson.info/andrew/
KWhat4 - 12 Aug 2007 04:45 GMT > .. > [quoted text clipped - 21 lines] > > Message posted via JavaKB.comhttp://www.javakb.com/Uwe/Forums.aspx/java-general/200708/1 Hopefully this will illustrate my insanity more effectively... I know its dirty, but the problem is at the very end when i try to read/write to an audio port. FYI I am using Java 1.5
package com.jargon.client.audio;
import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Line; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.Port; import javax.sound.sampled.TargetDataLine;
public class Test {
/** * @param args * @throws LineUnavailableException */ public static void main(String[] args) throws LineUnavailableException { AudioFormat objAudioFormat = new AudioFormat(8000.0F, 16, 1, true, false); Mixer objTargetMixer = null; Line objTargetLine = null;
System.out.println("Mixers:"); Mixer.Info[] aMixerInfo = AudioSystem.getMixerInfo(); for (int i = 0; i < aMixerInfo.length; i++) { /* Possible mixers for this computer ICH6 [plughw:0,0] ICH6 [plughw:0,1] ICH6 [plughw:0,2] ICH6 [plughw:0,3] ICH6 [plughw:0,4] Modem [plughw:1,0] Port ICH6 [hw:0] Port Modem [hw:1] */ if (aMixerInfo[i].getName().equalsIgnoreCase("Port ICH6 [hw:0]")) { objTargetMixer = AudioSystem.getMixer(aMixerInfo[i]); } System.out.println("\t" + aMixerInfo[i].getName()); } System.out.println();
//Now try to get a port on our target mixer System.out.println("Ports:"); Line.Info[] aLineInfo = objTargetMixer.getSourceLineInfo(); for (int i = 0; i < aLineInfo.length; i++) { /* Possible Port for the Target Mixer for this computer Capture source port */ if (aLineInfo[i] instanceof Port.Info) { Port.Info objPort = (Port.Info) aLineInfo[i]; objTargetLine = objTargetMixer.getLine(objPort); }
System.out.println("\t" + aLineInfo[i].toString()); }
//So now we have a mixer, we have a port... lets read/write data? //TODO This is where i bork the process! Note that i have tried all with no success.
//ClassCastException: com.sun.media.sound.PortMixer$PortMixerPort //TargetDataLine objInputDataLine = (TargetDataLine) objTargetMixer.getLine(objTargetLine.getLineInfo()); //TargetDataLine objInputDataLine = (TargetDataLine) objTargetLine; //TargetDataLine objInputDataLine = (TargetDataLine) AudioSystem.getLine(objTargetLine.getLineInfo());
//IllegalArgumentException: Line unsupported: interface TargetDataLine supporting format PCM_SIGNED 8000.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian //TargetDataLine objInputDataLine = (TargetDataLine) AudioSystem.getTargetDataLine(objAudioFormat, objTargetMixer.getMixerInfo()); } }
Knute Johnson - 12 Aug 2007 05:42 GMT >> .. >> [quoted text clipped - 101 lines] > } > } I don't know if you are a C programmer or not but there is an incongruity between C and Java naming in the audio business. In Java Ports are used to get controls, like volume and frame etc. Lines are used to capture or play audio data. SourceDataLines play, TargetDataLines capture. Mixers are really complicated as they can have Ports, SDLs and TDLs associated with them but may not.
Below is a simple example that gets audio data from a URL and plays it by sending it to a SourceDataLine. See the comments in the source for details.
Below that is a Sun program to list the ports on your computer. I'm sorry it is formatted so poorly but that is the way it is.
import javax.sound.sampled.*; import java.io.*; import java.net.*;
public class AudioExample { public static void main(String[] args) throws Exception { // get all the mixers Mixer.Info[] mixInfo = AudioSystem.getMixerInfo(); System.out.println("Mixers"); for (int i=0; i<mixInfo.length; i++) System.out.println(" " + mixInfo[i].toString());
// this is just source data, you can use whatever here // this file is from JavaSound, it is over 400k so might // take a while to download URL url = new URL("http://www.knutejohnson.com/22-new.aif"); AudioInputStream ais = AudioSystem.getAudioInputStream(url);
// format will probably be determined by source as in this case AudioFormat af = ais.getFormat(); System.out.println(af.toString());
// get a SDL with specified format from specified mixer SourceDataLine sdl = AudioSystem.getSourceDataLine(af,mixInfo[0]);
// open requires the format too sdl.open(af); // no sound until SDL is started sdl.start();
// read and write byte[] buf = new byte[1024]; int bytesRead; while ((bytesRead = ais.read(buf)) != -1) sdl.write(buf,0,bytesRead);
ais.close();
// empty the buffer sdl.drain(); // stop the line sdl.stop(); // close it cause we're done sdl.close(); } }
/* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */
import javax.sound.sampled.*;
public class ListPorts { public static void main(String[] args) { Mixer.Info[] aInfos = AudioSystem.getMixerInfo(); for (int i = 0; i < aInfos.length; i++) { try { Mixer mixer = AudioSystem.getMixer(aInfos[i]); mixer.open(); try { System.out.println(aInfos[i]); printPorts(mixer, mixer.getSourceLineInfo()); printPorts(mixer, mixer.getTargetLineInfo()); } finally { mixer.close(); } } catch (Exception e) { e.printStackTrace(); } } if (aInfos.length == 0) { System.out.println("[No mixers available]"); } System.exit(0); }
public static void printPorts(Mixer mixer, Line.Info[] infos) { for (int i = 0; i<infos.length; i++) { try { if (infos[i] instanceof Port.Info) { Port.Info info = (Port.Info) infos[i]; System.out.println(" Port "+info); Port port = (Port) mixer.getLine(info); port.open(); try { printControls(port.getControls()); } finally { port.close(); } } } catch (Exception e) { e.printStackTrace(); } } }
public static void printControls(Control[] controls) { for (int i = 0; i<controls.length; i++) { printControl(" ", "Controls["+i+"]: ", controls[i]); } if (controls.length == 0) { System.out.println(" [no controls]"); }
}
static boolean balanceTested = false;
public static void printControl(String indent, String id, Control control) { if (control instanceof BooleanControl) { BooleanControl ctrl = (BooleanControl) control; System.out.println(indent+id+"BooleanControl: "+ctrl); //try { // Thread.sleep(500); // ctrl.setValue(!ctrl.getValue()); // Thread.sleep(500); // ctrl.setValue(!ctrl.getValue()); //} catch (Exception e) {} } else if (control instanceof CompoundControl) { CompoundControl ctrl = (CompoundControl) control; Control[] ctrls = ctrl.getMemberControls(); System.out.println(indent+id+"CompoundControl: "+control); for (int i=0; i<ctrls.length; i++) { printControl(indent+" ", "MemberControls["+i+"]: ", ctrls[i]); } } else if (control instanceof EnumControl) { EnumControl ctrl = (EnumControl) control; Object[] values = ctrl.getValues(); Object value = ctrl.getValue(); System.out.println(indent+id+"EnumControl: "+control); for (int i=0; i<values.length; i++) { if (values[i] instanceof Control) { printControl(indent+" ", "Values["+i+"]:"+ ((values[i]==value)?"*":""), (Control) values[i]); } else { System.out.println(indent+" Values["+i+"]:"+ ((values[i]==value)?"*":"")+values[i]); } } } else if (control instanceof FloatControl) { FloatControl ctrl = (FloatControl) control; System.out.println(indent+id+"FloatControl: "+ctrl); //try { // Thread.sleep(500); // float x = ctrl.getValue(); // ctrl.setValue((float) (Math.random()*(ctrl.getMaximum() - // ctrl.getMinimum()) + ctrl.getMinimum())); // Thread.sleep(1000); // ctrl.setValue(x); //} catch (Exception e) {} //if (ctrl.getType() == // FloatControl.Type.BALANCE && !balanceTested) { // balanceTested = true; // for (float y = -1.0f; y<=1.0f; y+=0.02) { // ctrl.setValue(y); // System.out.println(" Set to "+y); // System.out.println(" res"+ctrl.getValue()); // } //} } else { System.out.println(indent+id+"Control: "+control); } } }
 Signature Knute Johnson email s/nospam/knute/
KWhat4 - 12 Aug 2007 07:09 GMT On Aug 11, 9:42 pm, Knute Johnson <nos...@rabbitbrush.frazmtn.com> wrote:
> >> .. > [quoted text clipped - 279 lines] > > read more ? Ok 12 hours later i think i finally figured it out! Ok so you can get a mixer for each of the "Lines" (I.E. each of the plugs on my sound card) and you can get ports for each of the mixers for the sole purpose of manipulating the analog data before its processed to the mixer. So I guess the question i am now at is how do i get the Mixer par of the Mixers and Port Mixers? I would like to be able to write out data to a mixer and also adjust the volume and stuff.
Andrew Thompson - 12 Aug 2007 07:32 GMT >On Aug 11, 9:42 pm, Knute Johnson <nos...@rabbitbrush.frazmtn.com> >wrote: ...
>[quoted text clipped - 279 lines] >> >> read more ? No thanks..
>Ok ... Note that it is not required (nor desirable) to quote over 280 lines of earlier conversation, to add the comment you made. Please *trim* when replying.
 Signature Andrew Thompson http://www.athompson.info/andrew/
KWhat4 - 12 Aug 2007 18:22 GMT > >On Aug 11, 9:42 pm, Knute Johnson <nos...@rabbitbrush.frazmtn.com> > >wrote: [quoted text clipped - 6 lines] > > >Ok ... Ok lets try this again...
Ok 12 hours later i think i finally figured it out whats going on.
So each one of my sound cards has 2 mixers (in the simplest case). One for the datalines and one for the ports. Now these two mixers are related but I can figure out how to programmatically match the two or if it even possible? Should the end user be selecting both mixers? Is there a way to derive one from the other?
Thanks for the help
Knute Johnson - 12 Aug 2007 18:12 GMT > Ok 12 hours later i think i finally figured it out! Ok so you can get > a mixer for each of the "Lines" (I.E. each of the plugs on my sound [quoted text clipped - 3 lines] > par of the Mixers and Port Mixers? I would like to be able to write > out data to a mixer and also adjust the volume and stuff. Reading and writing audio data is done on Lines. Mixers are a source of Lines and Ports. Look at my example to see how to determine which mixers are available. The Sun example will show you how to get Ports and their controls.
 Signature Knute Johnson email s/nospam/knute/
KWhat4 - 12 Aug 2007 21:28 GMT On Aug 12, 10:12 am, Knute Johnson <nos...@rabbitbrush.frazmtn.com> wrote:
> Reading and writing audio data is done on Lines. Mixersare a source of > Lines and Ports. Look at my example to see how to determine whichmixersare available. The Sun example will show you how to get Ports [quoted text clipped - 4 lines] > Knute Johnson > email s/nospam/knute/ Yes i can get both with little effort, its the fact that each comes from a different mixer that has thrown me off. It seems that i should be able to get ports and lines from the same mixer or at least be able to identify the appropriate other mixer form one of the two. I am not sure this is possible as I have found some information regarding the shortfalls of Java in this area.
Thanks again for you time and help.
Knute Johnson - 13 Aug 2007 01:18 GMT > On Aug 12, 10:12 am, Knute Johnson <nos...@rabbitbrush.frazmtn.com> > wrote: [quoted text clipped - 16 lines] > > Thanks again for you time and help. I know that it is very confusing and it confuses me too. But you should be able to do anything with JavaSound that you can do with any other system.
Maybe if you gave us a little overview of what you are actually trying to accomplish we could give you better directions.
 Signature Knute Johnson email s/nospam/knute/
KWhat4 - 14 Aug 2007 05:24 GMT > I know that it is very confusing and it confuses me too. But you should > be able to do anything with JavaSound that you can do with any other system. [quoted text clipped - 6 lines] > Knute Johnson > email s/nospam/knute/ So i thought i made a post but its not here so lets try again.
So there is a sound card. In the simplest case there is a mxier with a source and target lines, and there is a mixer with ports like volume. These mixers are related to each other, one is the actual binary lines the other is the analog controls, right? I was thinking that I should be able to match the two mixers because they are related. I.E. User selects the sound card (or mixer in this case) and we can both read and write data as well as manipulate the volume of these source and target lines. The problem i am seeing is that the user will have to select the matching mixers one for the binary lines and the other for the analog manipulation. I would like to avoid that if possible but I dont see a way to do that.
Thanks
Knute Johnson - 14 Aug 2007 19:01 GMT >> I know that it is very confusing and it confuses me too. But you should >> be able to do anything with JavaSound that you can do with any other system. [quoted text clipped - 22 lines] > > Thanks This is the first few output lines of the ListPorts program. I only have one sound card so I know it is a little different.
Primary Sound Driver, version Unknown Version SigmaTel Audio, version Unknown Version Primary Sound Capture Driver, version Unknown Version SigmaTel Audio, version Unknown Version Java Sound Audio Engine, version 1.0 Port SigmaTel Audio, version 5.10
The 'Port SigmaTel Audio, version 5.10' is the port mixer. The ports are LINE_IN, SPEAKER and MICROPHONE. These are the same ports that you would use to get controls for any mixer. Since I don't have two sound cards I don't know for sure but I would think that you will have Primary Sound drivers, Secondary Sound drivers, Java Sound Audio Engine and two Port mixers (Maybe you could post the output from your computer as above). In any case the SPEAKER port controls for a given sound card will work with any any source mixer. So I wouldn't give your user the option of selecting the port mixer, I would select that for him based on the sound card that he selects.
 Signature Knute Johnson email s/nospam/knute/
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|