# Java Sound API : Zuordnung Port-Mixer zu Input-Mixer



## Mithotyn (15. Jan 2010)

Hallo zusammen!

Ich kämpfe mich jetzt schon seit Stunden durch Google, Foren, Tutorials und Docs und finde keine Lösung für mein Problem.

Ich habe mittlerweile herausgefunden wie ich Mixer verwende um mir zur Aufnahme entsprechende TargetDataLines zu holen. Auch kann ich die Mixer abfragen um den Port-Mixer zu finden, um zwischen Line-In/Mikrofon umzuschalten und die Aufnahmelautstärke zu ändern.

Meine Frage ist nun die:

Ich habe MEHRERE (identische) Soundkarten im System (Windows) installiert. Demnach habe ich mehrere Input-Mixer und mehrere Port-Mixer.

Wie kann ich nun herausfinden welche Mixer zur physikalisch gleichen Soundkarte gehören? Damit ich im Programm auch den Lautstärkeregler [Soundkarte-1] zur Aufnahme-Quelle [SoundKarte-1] zuordnen kann.

Ihr versteht was ich meine?

Gruß Joachim


----------



## Spacerat (15. Jan 2010)

Mithotyn hat gesagt.:


> Ihr versteht was ich meine?


Ehrlich gesagt... nicht wirklich.
Du hast deine Mixer bzw. deine Ports und von diesen bekommst du eine Line. Das Line-Interface implementiert die Methode [c]getControl(Control.Type control)[/c]. Damit bekommt man immer die Regler jenes Ports, auf welchem die Line instanziert wurde. Mit zuordnen ist da nicht viel.


----------



## Mithotyn (15. Jan 2010)

Hmm... Das kann ich nicht bestätigen.


```
TargetDataLine tdl = AudioSystem.getTargetDataLine(new AudioFormat(8000, 8, 1, true, true));
		
tdl.open();

System.out.println("Anzahl Controls = " + tdl.getControls().length);
		
tdl.close();
```

Das liefert immer 0.

Macht rein logisch auch Sinn, wenn man sich die Hierarchie im Anhang mal anschaut. TargetDataLine implementiert erst DataLine und dann Line. Aber es implementiert nicht Port. Ich kann von TargetDataLine also nicht auf den zugrundeliegenden Port zugreifen. "getControls()" mag zwar vorhanden sein, liefert aber nur im Falle eines Ports tatsächlich die Controls.

Gruß


----------



## Mithotyn (15. Jan 2010)

Ich hab nochmal ne Grafik angehängt, die ich eben schnell zusammengebaut hab und die mein System wiedergibt.

Ich habe also eine "Realtek HD Audio" Soundkarte. Die stellt Java insg. 4 Mixer zur Verfügung. Um also Sound aufzunehmen, muss ich eine TargetDataLine vom *Input-Mixer* holen. Um die Ports zu steuern, muss ich diese aber vom *Port-Input-Mixer* holen.

Obwohl in Java 4 verschiedene (und noch etliche weitere) Mixer angezeigt werden, handelt es sich physikalisch um nur EINE Soundkarte.

Ich bräuchte also jetzt eine Möglichkeit, die verschiedenen Mixer pro Soundkarte zusammenzufassen. So dass ich später, wenn ich mehrere identische (USB-) Soundkarten am System angeschlossen habe, auch wirklich den Port der Soundkarte konfiguriere, von der ich auch die TargetDataLine bekommen habe.

In der Grafik ist mit der roten Linie der logische Pfad des Audiosignals vom Eingang der Soundkarte bis zur Anwendung markiert. Der gestrichelte Teil in der Mitte, der fehlt mir. Ich kann einen Port von irgend einem Mixer konfigurieren und kann von einem anderen Mixer aufnehmen. Dass beide aber zusammengehören, kann ich nicht feststellen.

Gruß Joachim


----------



## Spacerat (15. Jan 2010)

Nu' haste mich aber da liegen... Ich hab' mal bei mir alle möglichen TDLs abgefragt und keine einzige davon lieferte auch nur eine Control... das Array blieb immer leer. In der API-Doku hab' ich auch nichts finden können (die ist ja auch sowas von gut...). Ich gehe mal davon aus, das man dazu verdammt ist, die Eingangssignale softwaremässig "von hand" zu mischen. Ganz einverstanden bin ich damit aber noch nicht... Vllt. bringts was, wenn man sich die Control vom Portmixer holt und konkret den Port auswählt von wo man die TDL haben will.
	
	
	
	





```
TargetDataLine tdl = AudioSystem.getTargetDataLine(new AudioFormat(8000, 8, 1, true, true), portmixerinfo);
```


----------



## Mithotyn (15. Jan 2010)

Hi!

Hehe... Danke für die Bestätigung, dass es nicht an mir liegt.

Dein Vorschlag geht auch nicht. Das hatte ich auch schon probiert. Ich kann natürlich eine TDL nur von dem Mixer holen, der auch TDL's zur Verfügung stellt. Der Port-Input-Mixer stellt aber außer den Ports nix anderes zur Verfügung, so dass eine "LineUnsupported"-Exception geworfen wird.

So wie es aussieht, gibt es keinerlei Möglichkeit für das was ich brauche. (*)

Controls gibt es augenscheinlich nur bei Mixer und Port (Lautstärke, Balance, usw..). Eine TLD nimmt ja nur noch das, was der Mixer an Daten hat und leitet sie an die Anwendung. Sind alles einzelne, voneinander getrennte Lines mit eigenen Aufgaben und Möglichkeiten....

(*) Außer: Ich vergleiche die Namen der Mixer. Beim Port-Mixer steht noch "Port " vorne dran. Ansonsten heißen die Mixer identisch. Mag bei einer Soundkarte noch gehen, wie es bei mehreren identischen aussieht, weiß ich nicht. (Die kommen die Tage erst mit der Post)

Auf Unix-Systemen werden augenscheinlich die Hardware-Pfade noch mit angegeben. In Windows allerdings nicht.


Gruß Joachim


----------



## Mithotyn (15. Jan 2010)

Hi zusammen!

Ich hab mir mal die Sourcen der JDK runtergeladen und bin dem ganzen mal auf den Grund gegangen. Also es gibt in der Sound API mehrere MixerProvider, die eben Mixer zur Verfügung stellen. U.A. gibt dort den "DirectSoundMixerProvider" und den "PortMixerProvider". Beides sind eigene Klassen, die beim Ermitteln der vorhandenen Mixer nacheinander aufgerufen werden.

Der "DirectSoundMixerProvider" greift dabei auf native DirectX API's zurück, genauer auf die von "DirectSound". Die enumerierten Mixer werden dann als "DirectSoundMixer" auch zurückgegeben. In der Klasse "DirectSoundMixer" sind die Methoden implementiert, die DataLines zurückgeben. Die Klasse implementiert aber NUR TDL und SDL, eben keine Ports.

"PortMixerProvider" dagegen durchläuft native Win32 API's und ermittelt darüber vorhandene Mixer. Hier werden nun prinzipiell die gleichen Mixer gefunden wie beim "DirectSoundMixerProvider". Allerdings implementieren die Methoden im "PortMixer" nur Ports und keine DataLines. Auch wird (da hatte ich recht) dem Name der Mixer statisch ein "Port " vorangestellt.

Also:

Obwohl es sich im Betriebssystem um ein und denselben Mixer handelt, listet Java diese Mixer mehrmals mit unterschiedlichen "Features" auf. Einmal als "DirectSoundMixer" mit SDL und TDL und einmal als "PortMixer" mit Ports. Die Mixer agieren jeweils eigenständig (es gibt eine simple "List" aller vorhandenen Mixer) und lassen sich rein logisch nicht miteinander in Verbindung bringen.

Die einzige Möglichkeit besteht tatsächlich darin, den Namen des Mixers zu vergleichen, da bei dem Portmixer ja lediglich "Port " vorangestellt wird.

Das muss ich jetzt nur noch bei mehreren identischen Soundkarten prüfen. 

Wie ich in anderen Beiträgen und im Internet schon feststellen musste, ist die Java Sound API echt scheiße....

Gruß Joachim


----------



## Spacerat (16. Jan 2010)

Gute Idee mit dem Quelltext...
Hab' mir vor kurzem mal dieses hier installiert (als Eclipse-Plugin). Damit lässt sich der Quellcode sehr gut zurückverfolgen.
Beim Zurückverfolgen fällt einem irgendwann eine private Methode [c]enableControls()[/c] in der Klasse (Achtung: ) [c]PortMixer.PortMixerPort[/c] auf, welche dort unter anderem von [c]implOpen()[/c] aufgerufen wird.
Also mal rein hypothetisch: Kann es sein, das der Port erst geöffnet werden muss, bevor er selbst bzw. seine Lines Controls zurückgeben?


----------



## Mithotyn (16. Jan 2010)

Nabend!

Ja das stimmt. Der Port muss erst offen sein, bevor er Controls zurückgibt. 

Das hab ich in meinem Quelltext (siehe oben) auch berücksichtigt. Hilft aber trotzdem nichts bei dem Problem, weils nix dran ändert. 


Gruß Joachim


----------



## Spacerat (16. Jan 2010)

[c]tdl.open()[/c]? Damit öffnest du aber die Line und nicht den Port. Das portControlArray wird aber erst erstellt, wenn [c]portMixerPort.open();[/c] aufgerufen wird. Die Instanzen der Controls dürften (lt. Quelltext) immer die selben sein, ob sie nun von der Line oder vom Port geholt werden. Das Sound-API ist im übrigen kein API... es ist die Hölle :lol:


----------

