in english IMMD IV Hauptseite Zurück Nach oben Weiter Hilfe Rie - 14. Jan. 1997

AKBP-II 1997: Gruppe 5


Audio-Multiplex-Devicetreiber

Grundprinzip

Unser Multiplex-Audio-Device ist als Streams-Multiplex Devicetreiber für Solaris 2.5 realisiert. Es bietet den bestehenden Applikationen /dev/audio und /dev/audioctl und schickt die ankommenden Datenströme, geeignet gemischt, an das ``originale'' /dev/audio.

Jeder der Kanäle besitzt eigene ``Device-Einstellungen'' (struct audio_info), die die Benutzerprogramme individuell wählen können (über ioctl() Aufrufe an /dev/audio und /dev/audioctl; die Zuordnung audioctl->audio erfolgt über die PIDs der öffnenden Prozesse. Für unser Device sind relevant

Der Unterschied zwischen /dev/audio und /dev/audioctl ist lediglich, daß /dev/audioctl von mehreren Programmen gleichzeitig geöffnet werden kann, die darüber ioctl()Aufrufe absetzen um Lautstärke etc. zu ändern.
Programme wie gaintool oder audio_keys haben daher ein Problem wenn sie auf unser /dev/audioctl zugreifen, da sie damit ja nur ``ihren'' Kanal (zu ihrer PID) steuern können. Diese Programme müssen entweder mit entsprechenden Parametern dazu überredet werden, auf das originale /dev/audio (bei uns /dev/audioctl.orig) zuzugreifen, oder -- falls keine derartige Option besteht -- auf die Benutzung verzichtet werden (bzw. die Binaries gepacht werden).

Zur Steuerung des Mischvorgangs und der ``globalen'' Lautstärke haben wir ein kleines Tool, ``AudioMuxCtl'', geschrieben, das sowohl Zugriff auf das ``originale'' /dev/audioctl als auch auf unsern Devicetreiber hat (siehe obiges Diagramm).

Das Programm bietet folgende Optionen:

Usage:
        audioctl [-help] [-link] [-xlink]
 
        -help    gives you this message
        -link    will only create the link and loop forever, without
                 the X interface
        -xlink   start the X interface and link the devices
 
The default behaviour is to start the X interface and expect
the devices to be linked by an earlier "audioctl -link" call
                                                         chwindpa 97
Beabsichtigte Nutzung ist: beim Booten mit audioctl -link & die Verbindung zwischen original-Audio-Device und Multiplex-Treiber herstellen, und später unter X audioctl ohne Parameter starten, um Kontrolle über die Kanäle und den Mischvorgang zu bekommen.

Streams

Der Treiber benutzt die System V Release 4 Streams. Die Streams-Mechanismen sehen bereits sog. ``Multiplexors'' vor, d.h. Treiber die mehrere ``upper queues'' (Ein-/Ausgabequeues aus Userlevel-Richtung) und mehrere ``lower queus'' besitzen, und den Datenverkehr komplett selbst in der Hand haben.

In unserem Fall handelt es sich um einen ``Multiplexor'' mit mehreren upper queues und einer lower queue. Die Verbindung der lower queue mit /dev/audio muß durch einen Userlevel-Prozeß mittels des I_LINK-ioctl()s erfolgen.

Die oberen Queues werden beim Öffnen von /dev/audio als sog. ``Clone-Devices'' angelegt, d.h. jeder öffnende Prozeß bekommt eine eigene Instanz des Stream-Heads geliefert.

In der Put-Prozedur der oberen write queues werden alle ioctl() Aufrufe abgefangen (Ausnahme: AUDIO_DRAIN -- diese Kontrollnachrichten werden erst bestätigt, wenn alle Daten der Queue bearbeitet sind). Datenpakete werden von der put-Prozedur in die entsprechende upper-queue eingehängt. Die von dem Flow-Control Mechanismus angeworfene upper write service Prozedur macht dann ein qenable() auf die Ausgabequeue. Die dadurch getriggerte lower write service-Routine liest dann aus allen upper queues Daten und mischt diese zu jeweils neuen Paketen zusammen, die ans Audiodevice weitergereicht werden.

Um die Zusammenarbeit mit unserm audioctl-Tool zu unterstützen haben wir einen zusätzlichen ioctl() implementiert, mit dem das Device dem Userlevel-Programm (i.e. audioctl) mitteilt, welche anderen Programme (PID und Programmname) es geöffnet haben.

Mischen & Bitratenkonvertierung

Funktioniert mit 44100Hz, 16Bit linear, Stereo, sowie beliebige Sampleraten, 8Bit mu-Law kodiert, Mono. Unsere upper queues bieten jeweils eine ``generische Funktion'' an, die der lower queue service-Prozedur das nächste 16bit Sample mit der gewünschten Lautstärke liefert (d.h. sämtliche evtl. notwendige Konvertierung findet in dieser Routine statt). Daher ist die Erweiterung auf die übrigen vom Standard-/dev/audio unterstützten Formate relativ unproblematisch. (Wurde aber wegen untergeordneter Priorität bisher nicht unternommen).

Zur Konvertierung der Bitrate benutzen wir den Bresenham-Algorithmus, der eigentlich zum Zeichnen von Linien gedacht ist. Er liefert, mittels einer Zustandsvariablen, eine elegante (und schnelle) Entscheidung, ob ein Sample aus dem gegebenen Eingabestrom benutzt werden soll bzw. ein ``erdachtes'' Sample eigefügt werden muß. (Man kann es sich so vorstellen: es soll eine Linie von (0,0) nach beispielsweise (44100,8000) gezogen werden. Es werden also 44100 ``Schritte'' nach rechts gemacht, davon 8000 Schritte nach rechts+oben. Bei jedem Schritt nach rechts+oben wird ein ``original''-Sample eingefügt).
Die erdachten Samples haben bei uns jeweils den Wert des letzten eingelesenen Samples, so daß dadurch merkliche Oberwellen auftreten (der Anti-Aliasing Tiefpaß der Audio-Einheit hat natürlich bei 44.1kHz Samplingrate einen Durchlaßbereich bis 22kHz, d.h. aus dem Bereich z.B. 0-8000kHz kommt einiges an Oberwellen durch).

Dieses Problem läßt sich mit einem digitalen Tiefpaß-Filter, der entsprechende Oberwellen aus dem Datenstrom entfernt lösen. Dieser sitzt ebenfalls in der ``generischen Funktion''. Im Idealfall wäre dieser Filter auf die jeweils zu konvertierende Samplingrate zugeschnitten, mangels Prozessorleistung unseres Testrechners (Sun SS10-20) benutzt die neueste Version allerdings eine stark vereinfachte Version (Mittelwert der letzten 11 Samples).

Rechenleistungsbedarf

Es wurden nur stichprobenartige Tests durchgeführt; unsere Test-SS10-20 zeigte sich bereits mit zwei Kanälen an der Grenze ihrer Leistungsfähigkeit angelangt. Auf den SS10-40 (Entwicklungs-Rechner) waren zumindest zwei Kanäle im ungestörten Betrieb gut machbar. Auf einer SS20 (2 CPUs) konnten dagegen vier MPEG-Audio Decoder ohne größere Probleme parallel betrieben werden (auf einer Ultra1 war das Ergebnis entsprechend besser).

Da nur Rechenzeit benötigt wird, falls überhaupt ein Programm Audiodaten sendet, kann man die Benutzung im ``täglichen'' Betrieb trotzdem verantworten (weitergehende Tests zur Stabilität vorausgesetzt; das Modul macht jedenfalls bisher einen sehr stabilen Eindruck).

Bernhard Rümenapp, bdruemen@cip.informatik.uni-erlangen.de
und Christoph Windpassinger, windpassinger@informatik.uni-erlangen.de


Unser Server | Brief an Webmaster | Navigationshinweise | Suche