Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / August 2007

Tip: Looking for answers? Try searching our database.

Java Audio Help (Mixers and Ports)

Thread view: 
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.