Lowcost Multiroom-Audio mit IPS und Pulseaudio

Moin,

Ziel war ein Multiroom Audio System für ein neues Haus mit Zentralen Verstärkern und Lautsprecherkabeln in jeden Raum.

Hauptanforderung war, dass mehrere Quellen sich unabhängig in einzelne Räume schalten lassen können.

Fertige Multiroomsysteme kamen erst mal nicht in Frage um das knappe Baubuget nicht noch mehr zu belasten. Also habe ich rein auf das gesetzt was ich schon habe.

  • IPS Server in Windows VM
  • Linux VDR Server auf Debian Basis (selbst gebaut, keine fertige Distri)
  • Terratec Aureon 5.1 USB Soundkarte
  • Stereo Verstärker und Aktivboxen

Hauptproblem war, wie bekommt man die 5.1 Kanäle der Aureon in einzelne Stereo Pärchen, bzw. sogar Mono Kanäle die sich einzeln ansteuern lassen?

Unter Linux lies sich das relativ einfach mit Pulseaudio lösen. Hiermit konnte ich die Kanäle zu virtuellen Soundkarten aufdröseln und einzeln ansteuern.

Zum testen in der Mietswohnung habe ich die Front Buchse zum Wohnzimmer gemacht, die Küche ist an der Rear Buchse und das Bad an der Center/Sub.

Kurz zu den Begrifflichkeiten:
Pulseaudio = PA
Sink = Ziel, (virtuelle) Soundkarte

Zuerst habe ich in der PA Konfiguration diese beiden Parameter gesetzt, damit er nicht selbstständig rum mischt:
enable-remixing = no;
enable-lfe-remixing = no;

über das pavucontrol habe ich im Configuration Reiter die Profile alle auf Off gesetzt. Damit verschwinden sämtliche Karten aus den möglichen Ausgängen.

pa_config.jpeg

Danach wird die USB Karte hinzugefügt:


pacmd load-module module-alsa-sink sink_name=multiroom_card  sink_properties='device.description="Multiroom Card"' device=hw:3 channels=6 channel_map=front-left,front-right,rear-left,rear-right,front-center,lfe

Damit nachher die Umschaltung nahtlos klappt, erzeuge ich für jede Audioquelle virtuelle Karten für die einzelnen Räume:


pacmd load-module module-remap-sink sink_name=s1_Wohnzimmer master=multiroom_card channels=2 master_channel_map=front-left,front-right channel_map=front-left,front-right sink_properties='device.description="S1 Wohnzimmer"'
pacmd load-module module-remap-sink sink_name=s1_Kueche master=multiroom_card channels=2 master_channel_map=rear-left,rear-right channel_map=front-left,front-right sink_properties='device.description="S1 Kueche"'
pacmd load-module module-remap-sink sink_name=s1_Bad master=multiroom_card channels=2 master_channel_map=front-center,lfe channel_map=front-left,front-right sink_properties='device.description="S1 Bad"'

pacmd load-module module-remap-sink sink_name=s2_Wohnzimmer master=multiroom_card channels=2 master_channel_map=front-left,front-right channel_map=front-left,front-right sink_properties='device.description="S2 Wohnzimmer"'
pacmd load-module module-remap-sink sink_name=s2_Kueche master=multiroom_card channels=2 master_channel_map=rear-left,rear-right channel_map=front-left,front-right sink_properties='device.description="S2 Kueche"'
pacmd load-module module-remap-sink sink_name=s2_Bad master=multiroom_card channels=2 master_channel_map=front-center,lfe channel_map=front-left,front-right sink_properties='device.description="S2 Bad"'

S1 und S2 steht für Source, also die Quelle. Ja, momentan erscheint das noch unsinnig alles doppelt zu machen.

Die einzelnen virtuellen Karten werden jetzt jedenfalls wieder zusammengefasst:


pacmd load-module module-combine sink_name=S1 slaves=s1_Wohnzimmer,s1_Kueche,s1_Bad adjust_time=0
pacmd load-module module-combine sink_name=S2 slaves=s2_Wohnzimmer,s2_Kueche,s2_Bad adjust_time=0

Damit bekommt man wieder zwei virtuelle Karten auf die dann die einzelnen Zuspieler-Programme zugreifen.

In meinem einfachen Fall erst mal zwei mplayer die Webradio abspielen:


mplayer -ao pulse::S1 -cache 256 icyx://stream1.url
mplayer -ao pulse::S2 -cache 256 icyx://stream2.url

Im pavucontrol sieht das dann so aus:


Oben ist die Master Soundkarte. Man könnte hier global die Lautstärke regeln, z.B. wenn es an der Haustür klingelt.
Darunter sind die einzelnen Räume für Stream 1 und die Karte die die Räume zusammenfasst.

Hier das gleiche für Stream 2.

pa_streams.jpeg
Die mplayer wie sie mit den kombinierten Karten verbunden sind.

Derzeit spielen beide MPlayer gnadenlos parallel in allen Räumen ab. Die einzelnen virtuellen Karten werden nun auf Mute gestellt und dann einzeln wieder eingeschaltet und deren Lautstärke angepasst. Um also Stream 1 im Wohnzimmer und in der Küche zu hören, wird s1_wohnzimmer und s1_kueche nicht mehr stumm geschaltet. Im Bad könnte Stream 2 laufen und dort wird dann s2_bad eingeschaltet.

Hier kommt jetzt IPS ins Spiel. Für Windows gibt es pulseaudio Binarys. Damit kann übers Netzwerk pulseaudio gesteuert werden.
Damit das klappt muss noch der Zugriff übers Netz freigegeben werden.

pacmd load-module module-native-protocol-tcp auth-ip-acl="127.0.0.1;192.168.11.62/32" auth-anonymous=1

192.168.11.62 ist dabei mein IPS Server.

Für jeden Raum gibt es dann 2 Variablen. Lautstärke und Quelle. Beides Integer. Lautstärke als Intensity.100 und Quelle als eigenes Profil.

Quelle hat als Eigene Aktion nun dieses Script hinterlegt:


SetValue($IPS_VARIABLE , $IPS_VALUE);

switch($IPS_VALUE) {
	case 0:
		system('C:\pulseaudio\bin\pactl.exe -s vdrhd set-sink-mute "s1_Kueche" 0');
		system('C:\pulseaudio\bin\pactl.exe -s vdrhd set-sink-mute "s2_Kueche" 1');
		break;
	case 1:
		system('C:\pulseaudio\bin\pactl.exe -s vdrhd set-sink-mute "s1_Kueche" 1');
		system('C:\pulseaudio\bin\pactl.exe -s vdrhd set-sink-mute "s2_Kueche" 0');
	break;
}

Damit sendet IPS die Mute/Unmute Befehle für die virtuellen Karten.

Hinter der Lautstärke Variable liegt als Script:


SetValue($IPS_VARIABLE , $IPS_VALUE);
system('C:\pulseaudio\bin\pactl.exe -s vdrhd set-sink-volume "s1_Kueche" ' . $IPS_VALUE * 655);
system('C:\pulseaudio\bin\pactl.exe -s vdrhd set-sink-volume "s2_Kueche" ' . $IPS_VALUE * 655);

Um die gewünschte Lautstärke an die virtuelle Karte zu senden.

Im Webfront sieht es dann so aus:

Im Haus wird es dann erweitert auf die möglichen Zuspieler, wie z.B. Music Player Daemon (mpd), Line-In für CD/DVD Player, usw.

Das was noch fehlt und noch geplant ist, ist wenn ein Stream gar nicht gehört wird, dieser auch nicht gestartet ist. Ich möchte nicht rund um die Uhr mehrere Webstreams laufen haben und damit Bandbreite verschwenden.

Viel Spaß beim nachbauen der möglicherweise billigsten Multiroom-Audio Anlage. :smiley:

Gruß

Andreas

was noch zu erwähnen wäre ist, das ein sink auch auf einem anderen Rechner im Netz sein darf.
Mein Setup ist ähnlich. Ich nutze eine Software „Squeezebox“ squeezeslave - Light weight streaming audio player for Logitech’s Squeezebox audio server - Google Project Hosting auf mehreren Devices im Netz.

Gruss, Michael

Kleiner Nachtrag:
Ich habe das in der Zwischenzeit etwas universeller gestaltet.

Auf dem Server laufen derzeit zweit MPDs. Als Frontend dazu ist der „client175“ für jeweils einen der MPDs zuständig und im Webfront eingebettet.

Man ist nun nicht mehr starr auf eine Quelle festgelegt, sondern kann nahezu alles abspielen was der MPD her gibt.
Die Quelle „Merkur“ ist mein Arbeitsrechner, der selbst per Pulseaudio einen Netzwerkstream transparent an den Server übergeben kann. So kann ich z.B. Youtube Videos mit einem Klick von den lokal angeschlossenen Aktivboxen auf das Multiroom System schalten.

Mit steigender Personenanzahl werden dann einfach noch mehr MPDs und client175 hinzugefügt, damit jeder seine Musik hören kann.

Gruß

Andreas

Hallo Leute,

erst einmal einen sehr großen lob an den Bergdoktor! Deine Lösung ist echt mal ziemlich Cool! :cool::smiley:
Das ist genau das, was ich ebenfalls bauen möchte.
Ich verfolge diesen und den Link hier http://www.ip-symcon.de/forum/threads/20228-MultiRoom-Audio-per-RaspberryPi bereits seit einiger Zeit, und habe mir mal spontan einen RaspberryPI (RPI) gekauft. :smiley:

Wie muss ich nun vorgehen bzw. wo ist was Installiert?
1.) Basic Image auf RPI (läuft bereits)
2.) Pulsaudio
3.) MPD
4.) Client 175
Alles ist auf dem RPI installiert? Wie wird Client175 in das Front End eingebunden?
Oder muss Client 175 mit auf meinen ‚Webserver‘ installiert werden? So etwas dürfte bei mir schwer werden, da doch hierfür Linux benötigt wird oder?

Das Front End ist bei mir zur Zeit xampp, also eine Standart-Homepage auf einem Win7 x64 Laptop.

Mfg und Dank vorab, Christof

Ich hab ein paar Fragen:

  1. Wäre es möglich über das Webinterface die Lieder auszuwählen ?
  2. Kann ich meinem iTunes vortäuschen, dass der Linuxrechner ein Airplay-Empfänger ist und diesen „Eingang“ als Quelle verwenden ?
  3. Kann ich DLNA Geräte als „virtuellen Audiokanal“ einstellen, dass ich auf verschiedene DLNA Geräte streamen kann ?

Hallo,

auf den RPi kommt auf jeden Fall Pulseaudio und der MPD.
Der Client175 könnte auch darauf laufen. Ich werde das die Tage testen. Ein funktionsfähiger RPi hat es endlich in meinen Haushalt geschafft. Werde auf diesem die interne Soundkarte und die Terratec Aureon 5.1 USB anbinden, sofern die stabil daran läuft.
Der Client175 kann aber auch auf dem IPS Server laufen. Eine Python Umgebung (Version beachten), in Windows installiert, reicht aus. Der Client175 bringt seinen eigenen Webserver mit, oder kann in einen Apache integriert werden.
Mal sehen, ob der RPi das flüssig schafft, oder ob das zu viel wird.

Im übrigen habe ich derzeit in der 2.6er Version das Problem, dass der Client175, wenn er eingebettet ist, nicht funktioniert. Bei der 2.5er ging das. Dummerweise ist kürzlich die Subskription ausgelaufen und ich hab noch nicht verlängert. Könnte sein, dass ich eh auf Unlimited muss. Die 1000 Variablen werden knapp. :eek:

Wegen Apple oder DLNA hab ich keine Ahnung. Habe weder Apple noch DLNA zu Haus. Es gibt jedenfalls ein Plugin um von Pulseaudio zu einem Airport Express zu streamen, aber das ist wohl die falsche Richtung.
Zu DLNA finde ich auf anhieb nichts, aber das hat nichts zu heißen.

Gruß

Andreas

So, mal ein paar schlechte Neuigkeiten. :frowning:

Pulseaudio braucht auf dem RPi verdammt viel CPU durch das resampling. Man muss auf relativ schlechte Resampling Methoden schalten. Ich höre da leider Artefakte. Selbst auf 1GHz übertaktet wird schon bei einem MPD und nur 2 Ausgängen eine Last von 50-70% erzeugt.

Wenn man zu viele Ausgänge kombiniert, startet PA mit Realtime Priorität gar nicht erst vollständig. Ohne RT habe ich ständig Buffer-Underruns.

Die interne Soundkarte hat ein Delay von ca. 200-500ms gegenüber der USB Karte. Beide zu kombinieren und synchron zu halten ist mir bisher nicht gelungen.

Hat jemand von euch andere Erfahrungen gemacht? Ich fürchte fast, dass ich den höheren Stromverbrauch in Kauf nehmen muss und ein älteres Notebook dafür abstellen muss.
Btw. meine 1TB USB Platte läuft ebenfalls nicht am RPi.

frustrierte Grüße

Andreas

Hallo,

erst einmal Danke für deine Rückmeldung!
Zum Load von Pulseaudio, schau mal auf folgendem Link nach, da ist das Problem (inkl Fehleranalyse & behenbung) unter Feinheiten beschrieben.

http://wiki.ubuntuusers.de/PulseAudiohttp://

Gegen knackenden Sound soll alternativ auch der command „resample-method = speex-fixed-3“ helfen.

Zu meinem Problem:
…also kann man Client175 theoretisch unter XAMPP auf Win7 laufen lassen? :confused:

Mfg, Christof

Den Link hatte ich auch schon.
Speex-Fixed-3 schafft der RPi nicht. Jedenfalls nicht in dem Setup, bei dem die einzelnen Streams zusammen gemixt werden.

Mit „trivial“, also dem schlechtestem resampler, bringt er wenigstens etwas Ton raus.

In diesem Setup ist es ja so, dass alle Streams von allen Playern für jeden Ausgang immer zusammen gemischt werden und dann bei Bedarf auf Mute gestellt werden. Also müssen die Resampler ständig laufen und mischen, außer alle Ausgänge sind idle.

In dem anderen Thread wird der RPi nur verwendet um einen einzelnen RTP Stream entgegen zu nehmen und auf der internen Soundkarte auszugeben. Selbst das schafft er nur mit „trivial“.

Ein Weg der funktionieren könnte wäre: Ein MPD kann mehrere Ausgänge verwalten und könnte selbst mehrere Eingänge in PA bespielen. PA selbst könnte man dynamisch konfigurieren. Also module entladen und sinks und remaps so zusammen bauen wie die gerade benötigt werden.
Mir ist das zu kompliziert und das Ergebnis ist zweifelhaft, wenn selbst ein RTP Stream schon Mühe macht.

Derzeit läuft mein Setup auf einem älteren Thinkpad mit 2.26Ghz Pentium M. CPU läuft aktuell bei 800Mhz und hat bei einem Stream 20% CPU Last und bei 2 Streams geht es hoch auf 25-30%. Stromverbrauch ist leider etwas höher. (30W) Eventuell ist ein Atom Netbook da sparsamer, würde aber erst mal Investition bedeuten.

Den Client175 hatte ich dabei noch gar nicht auf dem RPi.

Der Client175 braucht gar kein XAMPP. Der braucht nur Python. Wer mag, der kann ihn in Apache einbauen, muss aber nicht und ist meist auch nicht nötig.

Keine Ahnung wie gut es funktioniert, aber man könnte noch über eine Linux VM in VMWare mit direkt durch gereichter USB Soundkarte sein Glück versuchen. Schlechte als im RPi kann ich es mir nicht vorstellen.

Gruß

Andreas

@bergdoktor:

Tolle Idee mit Pulseaudio. Ich bastel hier auch gerade damit rum.

Bekommt man auch den Ton vom VDR über Pulseaudio ins Netz?

Wenn ich das richtig verstanden habe läuft der Pulseaudio-Server bei dir auf dem VDR-Rechner?

Gruß,
Thorsten

Inzwischen läuft PA auf einem separaten Notebook. Der VDR braucht zu viel Strom um dauerhaft an zu sein.

Prinzipiell lässt sich jede Soundausgabe per Netzwerk oder direkt an PA übertragen. Wie gut das funktioniert muss man ausprobieren. Von einem Client per Xineliboutput simultan über combine lokal und Netz hab ich da keine guten Erfahrungen gemacht. Ton lief nach ein paar Minuten asynchron zum Bild. Die Funktion war zu unwichtig und ich habe es daher nicht weiter verfolgt.

Gruß

Andreas

Wollte mal kurz zurückmelden, dass ich das heute nach genau diesem Schema auch für meine Zwecke eingerichtet habe.
Danke dir, dass du damals diese Anleitung eingestellt hast.

Bei mir laufen zwei Mopidy Instanzen. Eingesetzt ist eine USB 5.1 Soundkarte. Die integrierte Realtek / Intel HD Audio 5.1 Karte (ALC663) habe ich nicht mehrkanalig ans laufen gebracht.

Anhängend meine Konfiguration in der /etc/pulse/system.pa [Pulseaudio als Systemdienst umgebogen].

Dabei spielt IP-Symcon auf Sink3 über Systembefehle Sprachbefehle, etc. und Sink1+2 jeweils für eine Mopidy Instanz.
hw:0 muss dabei an die Soundkarte angepasst werden. Infos hierzu über aplay -l

Weil sich die Reihenfolge der Soundkarten schonmal ändern kann, habe ich die USB Soundkarte in /etc/modprobe.d/alsa-base.conf mit

options snd-usb-audio index=0

fest auf Index 0 gesetzt.

Und die integrierte Soundkarte deaktiviert. In /etc/modprobe.d/blacklist-snd-hda-intel.conf

blacklist snd-hda-intel
load-module module-alsa-sink sink_name=multiroom_card   sink_properties='device.description="Multiroom Card"' device=hw:0  channels=4

load-module module-remap-sink sink_name=s1_Kueche  master=multiroom_card channels=2 master_channel_map=rear-left,rear-right  channel_map=front-left,front-right  sink_properties='device.description="S1 Kueche"'  remix=no
load-module module-remap-sink sink_name=s1_Bad master=multiroom_card channels=2  master_channel_map=front-left,front-right  channel_map=front-left,front-right  sink_properties='device.description="S1 Bad"'  remix=no

load-module module-remap-sink sink_name=s2_Kueche master=multiroom_card channels=2  master_channel_map=rear-left,rear-right  channel_map=front-left,front-right  sink_properties='device.description="S2 Kueche"'  remix=no
load-module module-remap-sink sink_name=s2_Bad master=multiroom_card channels=2  master_channel_map=front-left,front-right  channel_map=front-left,front-right  sink_properties='device.description="S2 Bad"' remix=no

load-module module-remap-sink sink_name=s3_Kueche master=multiroom_card channels=2  master_channel_map=rear-left,rear-right  channel_map=front-left,front-right  sink_properties='device.description="S3 Kueche"'  remix=no
load-module module-remap-sink sink_name=s3_Bad master=multiroom_card channels=2  master_channel_map=front-left,front-right  channel_map=front-left,front-right  sink_properties='device.description="S3 Bad"' remix=no


load-module module-combine sink_name=S1 slaves=s1_Kueche,s1_Bad adjust_time=0
load-module module-combine sink_name=S2 slaves=s2_Kueche,s2_Bad adjust_time=0
load-module module-combine sink_name=S3 slaves=s3_Kueche,s3_Bad adjust_time=0

Pulseaudio als Systemdienst gemäß dieser Anleitung.

Soundwiedergabe aus IP-Symcon (auf dem selben Host):

system("/usr/bin/paplay --client-name=SymconSprachAusgabe --device=S3 /tmp/symcon_tem1.wav");

Eventuell werde ich zur späteren Zeit meine Mopidy Scripte mal zusammenfassen und ggf. sogar als Modul anbieten. Sollte daran also Interesse bestehen, gerne mal schreiben. Technische Basis ist das Modul „WebsocketClient“ von Nall-Chan

Cool, das find ich super.

Mopidy kannte ich noch nicht. Muss ich mir genauer ansehen wo da der Vorteil liegt. Bisher laufen einfach nur zwei mpd Instanzen.

Mir ist aber direkt eine Kleinigkeit aufgefallen:
Das „remix=no“, bringt das einen bestimmten Vorteil? Latenz, CPU, oder was ganz anderes?

Bei mir laufen inzwischen 2 USB 5.1 Soundkarten und es ist von dem Notebook auf einen ODROID XU-4 gewandert.

Als zusätzlichen sink habe ich noch diese Zeile:
load-module module-native-protocol-tcp auth-ip-acl=„127.0.0.1;192.168.11.0/24“ auth-anonymous=1

Damit kann ich auf meinem Linux Rechner diesen Tunnel manuell hinzufügen und dynamisch Audio über den Multiroom laufen lassen.
load-module module-tunnel-sink-new server=vdr sink_name=vdrchannels=2 rate=44100

Ich plane es seit Jahren, aber komme nicht dazu direkt eine Library-Suche vom MPD und einen Playlist Editor im IPS Webfront zu bauen.

Viele Grüße

Andreas

Mopidy kann auch Spotify und andere Streamingdienste und lässt sich per Websocket JSON RPC steuern. Das bringt mir sofort ein Feedback (z.B. welches Lied läuft gerade, etc.). Zudem könnte ich hierüber ggf. die im Mopidy Webinterface gesetzte Lautstärke abfangen und an den aktuell passende Pulseaudio Sink senden. Ggf. praktisch wenn ich während der Auswahl einer Playlist mal schnell die Lautstärke verändere.

Remix=no ist einfach geschultet, dass ich ein Mixing (welches ja bei Stereo in und Stereo Out) auch nicht nötig ist, verhindern möchte. Insbesondere bei meinen Test, bei denen das ein oder andere noch etwas hakte.