java.sound.sample finde den Microfoneingang

melmager

Erfahrenes Mitglied
Ich wollte eigendlich übern Sound Microfoneingang was aufzeichnen -

Ich habe schon ettliche Codes durch aber noch keinen gefunden der mir ermittelt auf welchen Mixer mein Microfon eingang liegt (und den ich verstehe was da gemacht wird)

Eine Liste die ermittelt Welche Mixer im System ist habe ich schon
Ich kann auch schon die Mixer rausfiltern dir fürn Eingang zuständig sind

und dann hörts auf.

Über Port.Info sollte man ja rausfinden können os Microfon oder Line oder ... ist

Vom Mixer kann ich ja ne Liste abrufen welche Lines so da sind - und dat Port.Info ist ja eine erweiterung von der line.info .. soweit so gut.

Was mir bisher an den Codes die ich so gesehen habe aufgefallen ist:

die meisten gehen über eine Exeption.. sprich ich versuche die line.inf auf eine port.info zu casten .. fehlgeschlagen dann kann es noch z.B ein Clip sein oder..

Was mich zur ersten Frage führt kann man das nicht vom Cast feststellen ?

Code:
mixerInfo = AudioSystem.getMixerInfo();
        System.out.println("Available mixers:");
        for (int cnt = 0; cnt < mixerInfo.length; cnt++) {
            Mixer currentMixer = AudioSystem.getMixer(mixerInfo[cnt]);

            //if (currentMixer.isLineSupported(targetDLInfo)) {
            if (currentMixer.isLineSupported(portInfo)) {
                System.out.println("mixer: " + mixerInfo[cnt].getName() + " [index:" + cnt + "]");
                try {
                    Port tPort = (Port) currentMixer.getLine(portInfo);
                     //Port tPort = (Port) currentMixer.getLine(targetDLInfo);
                     System.out.println(tPort.getLineInfo());
                }
               catch (Exception e1) {
                   System.out.println(e1);
               }
            }

dat wirft mir das raus:
Code:
mixer: Port CK8 [hw:0] [index:5]
IEC958 Playback AC97-SPSA source port

dat programm:
Code:
 Line.Info[] tLineInfos = mixer.getTargetLineInfo();
            System.out.println("  Targets (" + tLineInfos.length + "):");
            for (int k = 0; k < tLineInfos.length; k++) {
                try {
                    TargetDataLine tLine = (TargetDataLine) mixer.getLine(tLineInfos[k]);
                    System.out.println("   Line: " + tLine.getLineInfo() + "\t(Name: " + tLine + ")");
                } catch (LineUnavailableException e) {
                    e.printStackTrace();
                } catch (ArrayIndexOutOfBoundsException e) {
                } catch (ClassCastException e) {
                    try {
                        Clip tClip = (Clip) mixer.getLine(tLineInfos[k]);
                        System.out.println("   Clip: " + tClip.getLineInfo() + "\t(Name: " + tClip + ")");
                    } catch (LineUnavailableException e1) {
                        e1.printStackTrace();
                    } catch (ClassCastException e1) {
                        try {
                            Port tPort = (Port) mixer.getLine(tLineInfos[k]);
                            System.out.println("   Port: " + tPort.getLineInfo() + "\t(Name: " + tPort + ")");
                        } catch (LineUnavailableException e2) {
                            e2.printStackTrace();
                        }
                    }

wirft dat raus

Code:
Port CK8 [hw:0]index 5
  Sources (2):
   Port: IEC958 Playback AC97-SPSA source port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@18ee9d6)
   Port: Capture source port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@19a0c7c)
  Targets (13):
   Port: Master target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@a9ae05)
   Port: Master Mono target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@1dff3a2)
   Port: PCM target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@1f42b49)
   Port: Surround target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@145e044)
   Port: Center target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@86c347)
   Port: LFE target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@17e6a96)
   Port: Line target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@87a5cc)
   Port: CD target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@1960f05)
   Port: Mic target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@b42cbf)
   Port: Phone target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@e5b723)
   Port: IEC958 Playback AC97-SPSA target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@15a8767)
   Port: Beep target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@6f7ce9)
   Port: Aux target port        (Name: com.sun.media.sound.PortMixer$PortMixerPort@171bbc9)

und nu ?

und step 2 - selbst wenn ich weiss welchen Mixer ich brauche weil da mein Mic drauf ist - wie wähle ich den an ?

nu habe ich ne Version die ich verstehe und scheinbar geht:
Code:
mixerInfo = AudioSystem.getMixerInfo();
     for (int cnt = 0; cnt < mixerInfo.length; cnt++) {
        Mixer currentMixer = AudioSystem.getMixer(mixerInfo[cnt]);
        System.out.println("mixer ["+cnt+"]: " + mixerInfo[cnt].getName());
        Line.Info[] tLineInfos = currentMixer.getTargetLineInfo();
        for (int li=0; li < tLineInfos.length; li++) {
           try {
             Line tLine = currentMixer.getLine(tLineInfos[li]);
             System.out.println("\tTarget Line: " + tLine.getLineInfo() );
           } catch (LineUnavailableException e) {
              System.out.println(e);
           }
        }
        tLineInfos = currentMixer.getSourceLineInfo();
        for (int li=0; li < tLineInfos.length; li++) {
          try {
            Line tLine = currentMixer.getLine(tLineInfos[li]);
            System.out.println("\tSource Line: " + tLine.getLineInfo() );
          } catch (LineUnavailableException e) {
            System.out.println(e);
          }
        }
      }

was mich etwas Überrascht:
ist das Ergebniss was bei rauskommt:
Code:
mixer [5]: Port CK8 [hw:0]
.......snipp ....
  Target Line: Mic target port
...... snipp ......
  Source Line: Capture source port

wiso ist ein Microfon ein Target ****? verwirrt bin ,,,

Edit:
so wie es im Moment aussieht kommt das Java System nicht an den Mic Eingang heran ...
 
Der Eingang ist doch nicht der „Mic target port“, sondern einer der beiden Eingänge „IEC958 Playback AC97-SPSA source port“ und „Capture source port“ oder?
 
Der Eingang ist doch nicht der „Mic target port“, sondern einer der beiden Eingänge „IEC958 Playback AC97-SPSA source port“ und „Capture source port“ oder?

jepp sollte der Capture Port sein - kann trotzdem nichts einlesen.
Ich habe mein Programm "Liste alle SoundQuellen auf" noch erweitert und lasse mir noch alle unterstützen Audioformate auflisten.

Und siehe da Mixer 5 unterstützt kein Audioformat.
Andre Mixer haben zwar unterstützte Audioformate aber Samplerate "unbekannt" und entsprechend bekomme ich eine Exeption weil das Audioformat was ich angebe nicht unterstützt wird.
Soweit ich es rausgefunden habe liegt das eher an der Schnittstelle zwischen ALSA und Java - sprich unter Linux komme ich mit dem Microfoneingang nicht weiter - leider
aber dat positive: Lerneffect ... :)
 
Zuletzt bearbeitet:
Was für ein Java verwendest du unter Linux? So ein Verhalten darf ja eigentlich nicht vorkommen, da sollte man nen Bug melden. Mit welchem Code testest du das?
 
Also aktuell habe ich den Code:

Code:
public class ListPorts {

    private Mixer.Info[] mixerInfo;
    private Mixer selmix = null;

    public void ListAudioInputDevices() {

        mixerInfo = AudioSystem.getMixerInfo();
        System.out.println("Available mixers:");
        for (int cnt = 0; cnt < mixerInfo.length; cnt++) {  // list Mixer
            Mixer currentMixer = AudioSystem.getMixer(mixerInfo[cnt]);
            System.out.println("mixer [" + cnt + "]: " + mixerInfo[cnt].getName());
            Line.Info[] tLineInfos = currentMixer.getTargetLineInfo();
            for (int li = 0; li < tLineInfos.length; li++) { //list Taret Lines
                try {
                    Line tLine = currentMixer.getLine(tLineInfos[li]);
                    System.out.println("\tTarget Line : " + tLine.getLineInfo());
                    if (tLineInfos[li] instanceof DataLine.Info) { //AudioFormats
                        DataLine.Info dataLineInfo = (DataLine.Info) tLineInfos[li];
                        AudioFormat[] supportedFormats = dataLineInfo.getFormats();
                        for (int frmlo = 0; frmlo < supportedFormats.length; frmlo++) {
                            supportedFormats[frmlo].toString();
                        }
                    }
                } catch (LineUnavailableException e) {
                    System.out.println(e);
                }
            }
            Line.Info[] sLineInfos = currentMixer.getSourceLineInfo();  // dat gleiche noch mal für Source
            for (int li = 0; li < sLineInfos.length; li++) {
                try {
                    Line sLine = currentMixer.getLine(sLineInfos[li]);
                    System.out.println("\tSource Line : " + sLine.getLineInfo());
                    if (sLineInfos[li] instanceof DataLine.Info) {
                        DataLine.Info dataLineInfo = (DataLine.Info) sLineInfos[li];
                        AudioFormat[] supportedFormats = dataLineInfo.getFormats();
                        for (int frmlo = 0; frmlo < supportedFormats.length; frmlo++) {
                            System.out.println("\t\t"+supportedFormats[frmlo].toString());
                        }
                    }
                } catch (LineUnavailableException e) {
                    System.out.println(2);
                }
            }
        }
    }

    public Mixer.Info getMixerInfo(int index) {
        return mixerInfo[index];
    }
}

Code:
public static void main(String[] args) {

        int value;
        ListPorts test = new ListPorts();
        test.ListAudioInputDevices();

        Scanner scanner = new Scanner(System.in);
        System.out.print("Inut Mixer ");
        int selmix = scanner.nextInt();
        System.out.println("Use Mixer :"+selmix);

        format = new AudioFormat(11025.0F, 16, 2, true, false);

        try {
            TargetDataLine tl = AudioSystem.getTargetDataLine(format, test.getMixerInfo(selmix));
            tl.open(format);
            tl.start();
            byte[] block = new byte[10];
            // int erg = tl.read(block, 0, 2);
            for (int lo = 0; lo < 100; lo++) {
                while (tl.available() <= 2) {
                    //wait
                }
                int tmp = tl.read(block, 0, 2);
                value = (block[1] << 8) | (block[0] & 0xFF);
                System.out.println(value);
            }
            tl.stop();
            tl.close();
        } catch (Exception ex) {
            System.out.println(ex);
        }

    }
}

Bei Mixer 5 listet er keine Audioformate auf und der Fehler:
java.lang.IllegalArgumentException: Line unsupported: interface TargetDataLine supporting format PCM_SIGNED 11025.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian

bei mixer 1 kommt z.B
PCM_SIGNED unknown sample rate, 16 bit, mono, 2 bytes/frame, little-endian

aber gleiche Fehlermeldung...

Mixer 5 ist der einzige der überhaupt der den auflistet: Source Line : Capture source port

Java Version 1.6.20 (ich weiss alt ...)

Unter XP mit Java 6.38 gehts auch nicht - wo ist mein Programmfehler ?

unknown sample rate scheint zu bedeuten jede Framerate sagen die bei jsresources
 
Zuletzt bearbeitet:
Bei mir sieht die Ausgabe von deinem Code so aus:
Code:
mixer [6]: Port Intel [hw:0]
	Target Line : Master target port
	Target Line : Headphone target port
	Target Line : PCM target port
	Target Line : Front target port
	Target Line : Front Mic target port
	Target Line : Front Mic Boost target port
	Target Line : Surround target port
	Target Line : Center target port
	Target Line : LFE target port
	Target Line : Line target port
	Target Line : Rear Mic target port
	Target Line : Rear Mic Boost target port
	Source Line : Front Mic Boost source port
	Source Line : Capture source port
	Source Line : Capture source port
	Source Line : Digital source port
	Source Line : Rear Mic Boost source port
Inut Mixer
, vollständig unter http://pastebin.com/cLRCAJc4

Vom Mixer kann ich ja ne Liste abrufen welche Lines so da sind - und dat Port.Info ist ja eine erweiterung von der line.info .. soweit so gut.

Was mir bisher an den Codes die ich so gesehen habe aufgefallen ist:

die meisten gehen über eine Exeption.. sprich ich versuche die line.inf auf eine port.info zu casten .. fehlgeschlagen dann kann es noch z.B ein Clip sein oder..
Eine SourceDataLine kann, muss aber nicht vom Typ Port sein. bei mir sind einige SourceDataLines auch vom Typ Clip.

So wie es aussieht liegen Mikrofoneingänge an einer TargetDataLine an, nicht an einer SourceDataLine. Jedenfalls schließe ich das daraus, dass mein Gnome 3 mir nur dann anzeigt, eine Java-Anwendung greife auf das Mikro zu, wenn ich TargetDataLines öffne.

[EDIT:]
Bei mir sieht es jetzt so aus:
Wenn ich mit Java alle TargetDataLines zum Lesen öffne, zeigt mir die Gnome Shell nur an, dass ich von einem Mikrofon Daten abhole. Es sollte also kein Problem sein, zur Not einfach die (wahrscheinlich einzige) TargetDataLine zu nehmen, die Daten führt.(siehe EDIT3)

[EDIT2:]
Kannst du mit anderen Anwendungen dein Mikrofon zum laufen bringen? Bei mir (Fedora 17, OpenJDK/IcedTea) hängt der allgemeine Mikro-Eingang (hoffentlich Hardwareunabhängig) auf dem Mixer „PulseAudio Mixer“ und ist dort die einzige TargetDataLine. Was die anderen TargetLines der anderen Mixer sollen, weiß ich nicht genau.

[EDIT3:]
Man kann nicht einfach von allen TargetDataLines, die sich öffnen lassen, Daten einlesen. Bei mir werden dabei nämlich von 4 TargetDataLines Daten aufgenommen, ich habe aber definitiv nur ein einziges Mikrofon. Die anderen TargetDataLines sind Stereo-LineIns, ich habe aber noch keinen Plan, wie ich die unterscheiden soll.

Aktueller Stand des Codes:
Java:
import java.util.Arrays;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Mixer.Info;
import javax.sound.sampled.TargetDataLine;

public class CaptureTest {

	public CaptureTest() {

		System.out.println("Supported File Types: "
				+ Arrays.toString(AudioSystem.getAudioFileTypes()));

		// try first: let javax.sound API determine MICROPHONE input
		// DOES NOT WORK!
		// No line matching MICROPHONE source port is supported.
		// try {
		// Line.Info micInfo = AudioSystem.getLine(Port.Info.MICROPHONE)
		// .getLineInfo();
		// testLines(new Line.Info[]{micInfo}, "–MICROPHONE–");
		// } catch (LineUnavailableException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }

		Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
		for (Info mixerInfo : mixerInfos) {
			System.out.println("Mixer: " + mixerInfo.toString() + " : "
					+ mixerInfo.getDescription());
			Line.Info[] lineInfos;
			// SourceDataLines
			// Omitted since all Microphones are available via TargetLines
			// lineInfos = AudioSystem.getMixer(mixerInfo).getSourceLineInfo();
			// testLines(lineInfos, "SourceLines");

			// TargetDataLines
			lineInfos = AudioSystem.getMixer(mixerInfo).getTargetLineInfo();
			testLines(lineInfos, "TargetLines");

		}

	}

	/**
	 * waste some time to allow to check which lines are opened (with
	 * gnome-shell)
	 */
	private void wait2() {

		try {
			Thread.currentThread().sleep(5000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
	}

	private void testLines(Line.Info[] lineInfos, String str) {
		for (Line.Info lineInfo : lineInfos) {
			System.out.println("\t" + str + lineInfo.toString() + " : "
					+ lineInfo.getLineClass());
			if (!AudioSystem.isLineSupported(lineInfo)) {
				System.out.println("\t\tLine not supported");
				continue;
			}
			if (lineInfo.getLineClass().equals(Clip.class)) {
				System.out.println("\t\tClips not supported");
				continue;
			}
			Line line;
			try {
				line = AudioSystem.getLine(lineInfo);
				// Ignore ports, SourceLines, SourceDataLines, …
				if (!(line instanceof TargetDataLine)) {
					System.out.println("\t\tignored");
					continue;
				}
				testRead((TargetDataLine) line);
			} catch (LineUnavailableException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			wait2();
		}
	}

	private void testRead(TargetDataLine tdl) {
		try {
			tdl.open();
			tdl.start();
			byte[] data = new byte[44100];
			System.out.println(tdl.getBufferSize());
			System.out.println(tdl.getFormat());
			System.out.println(tdl.read(data, 0, 44100));
			System.out.println(tdl.getLongFramePosition());
			System.out.println(Arrays.toString(data));
		} catch (LineUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new CaptureTest();
	}

}
und die dazu gehörige Ausgabe:
Code:
Supported File Types: [WAVE, AU, AIFF]
Mixer: PulseAudio Mixer, version 0.02 : the ear-candy mixer
	TargetLinesinterface TargetDataLine supporting 42 audio formats, and buffers of 0 to 1000000 bytes : interface javax.sound.sampled.TargetDataLine
50004
PCM_UNSIGNED unknown sample rate, 8 bit, 6 channels, 6 bytes/frame, 
44100
7350
[121, 121, 121, 120, 120, 121, 121, 121, 121, 122, 122, 121, 121, 121 ~~~~~]
Mixer: default [default], version 1.0.25 : Direct Audio Device: default, default, default
	TargetLinesinterface TargetDataLine supporting 512 audio formats, and buffers of at least 32 bytes : interface javax.sound.sampled.TargetDataLine
88200
PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian
44100
11136
[-66, -5, -43, -7, 76, -7, 39, -5, -91, -6, -83, -5, -101, -4, 81, -3, -80, -4, -95, ~~~~~]
Mixer: Intel [plughw:0,0], version 1.0.25 : Direct Audio Device: HDA Intel, ALC887 Analog, ALC887 Analog
Mixer: Intel [plughw:0,1], version 1.0.25 : Direct Audio Device: HDA Intel, ALC887 Digital, ALC887 Digital
Mixer: Intel [plughw:0,2], version 1.0.25 : Direct Audio Device: HDA Intel, ALC887 Analog, ALC887 Analog
	TargetLinesinterface TargetDataLine supporting 24 audio formats, and buffers of at least 32 bytes : interface javax.sound.sampled.TargetDataLine
88200
PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian
44100
11296
[92, -2, -112, -3, -30, 1, 72, 3, -3, 2, 67, 2, -66, 2, 19, 3, 94, 7, 50, 5, 28, 5, 43, 4, ~~~~~]
Mixer: Intel [plughw:0,3], version 1.0.25 : Direct Audio Device: HDA Intel, HDMI 0, HDMI 0
Mixer: Port Intel [hw:0], version 1.0.25 : HDA Intel, Intel IbexPeak HDMI
	TargetLinesMaster target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesHeadphone target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesPCM target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesFront target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesFront Mic target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesFront Mic Boost target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesSurround target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesCenter target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesLFE target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesLine target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesRear Mic target port : interface javax.sound.sampled.Port
		ignored
	TargetLinesRear Mic Boost target port : interface javax.sound.sampled.Port
		ignored
Wobei ~~~~~ jeweils eine Auslassung für viele weitere verschiedene Elemente des Arrays ist.

Ich kann also zumindest schon mal vom Mikrophon und 2 Line-Ins Daten einlesen. Jetzt brauchen wir nur noch Parameter, anhand denen wir entscheiden können, welchen dieser Eingänge wir nehmen sollen.
Kannst du die Ausgabe von meinem Code hier bitte noch posten, damit ich vergleichen kann?
 
Zurück