Seite 1 von 2

Konfiguration von BruteFIR und ALSA

Verfasst: 05.05.2015, 21:02
von Nova Auralis
Seid gegrüßt liebe Forenten,

einige der unten stehenden Fragen habe ich bereits andernorts gestellt, hielt es jedoch für angemessen dafür einen eigenen Thread zu starten.

Es geht grundsätzlich darum, eine möglichst simple sowie minimalistische Lösung zur Integration von BruteFIR zu finden, ohne auf Jack Audio und Co. zurückgreifen zu müssen. Mein einer Rechner muss dabei jegliche Aufgaben gleichzeitig bewältigen, das heißt nicht nur das Falten, sondern auch die Wiedergabe über unterschiedliche Software (Audioplayer, Videoplayer, Browser).

Im oben verlinkten Thread hatte mich Frank auf einen Beitrag von Martin hingewiesen. Diesbezüglich stellten sich mir folgende Fragen:
Nova Auralis hat geschrieben:Ich verstehe noch nicht so richtig, wieso Martin hier einen so umständlichen Ansatz mit Loopback verfolgt, während in den meisten anderen BruteFIR-Konfigurationen stets nur Direktzugriffe auf ALSA-Geräte zu sehen sind. Gehen solche Konfigurationen (z.B. hier) ausschließlich von Convolving-PCs aus, welche das Audio Signal über einen Eingang empfangen, die entsprechenden Faltungen erledigen, um das Ganze dann wieder über einen bzw. mehrere Ausgänge rauszuschicken? Würde eine solche Konfiguration in meinem Fall scheitern, weil der Zugriff auf ALSA-Geräte normalerweise exklusiv geschieht, sprich immer nur eine Software zur selben Zeit darauf zugreifen kann?
Als mögliche Lösung kam mir dann folgende Idee:
Nova Auralis hat geschrieben:Für den Fall, dass meine Vermutungen stimmen, hatte ich folgende Überlegungen zu einem vielleicht möglichen Trick angestellt. Was wäre, wenn ich meine Wiedergabe-Software stattdessen dazu anhalte auf ein virtuelles Gerät (dmix) zuzugreifen, welches wiederum als "Slave" einen Dummy-Ausgang (HDMI) nutzt? Auch BruteFIR wird dabei im Eingang auf dieses virtuelle Gerät konfiguriert, die Ausgänge können dann ungestört über die korrekten ursprünglich geplanten ALSA-Geräte laufen. Hier eine Konfiguration, wie in etwa ich mir das vorstelle:

Ausschnitt aus der asound.conf:

Code: Alles auswählen

pcm.VIA_PCI {
   type hw
   card 2
   device 0
}

pcm.Dummy_HDMI {
   type hw
   card 0
   device 3
}

pcm.dmixer {
   type dmix
   ipc_key 1024
   slave.pcm "Dummy_HDMI"
   slave {
      periods 2
      period_size 4096
      buffer_size 8192
      rate 96000
      format S32_LE
      channels 2
   }
   bindings {
      0 0
      1 1
   }
}

pcm.!default {
   type plug
   slave.pcm "dmixer"
}
Ausschnitt aus der .brutefir_config:

Code: Alles auswählen

input "left_in", "right_in" {
        device: "alsa" { device: "pcm.!default"; ignore_xrun: true; };
};

output "left_out", "right_out" {
        device: "alsa" { device: "pcm.VIA_PCI"; ignore_xrun: true; };
};
Probiere ich die zitierten Konfigurationen aus, erhalte ich von BruteFIR allerdings eine Fehlermeldung, die da lautet:

Code: Alles auswählen

ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM pcm.!default
ALSA I/O: Could not open audio input "pcm.!default": No such file or directory.
Failed to init input device.
Failed to initialise digital audio interfaces.
Wo könnte das Problem liegen? Seltsam ist, dass BruteFIR mit "pcm.VIA_PCI" als Eingang problemlos arbeitet, bei "pcm.Dummy_HDMI" hingegen gibt es wieder die genannte Fehlermeldung. An der Art der Deklaration (anstatt dem gewöhnlichen Direktzugriff über "hw:...") scheint es also folglich nicht liegen zu können?

Beste Grüße,
Jannis

Verfasst: 05.05.2015, 21:50
von Tinitus
Hallo Jannis,

ich bin weit davon entfernt ein Spezialist zu sein, aber vielleicht hilft die das weiter:

http://www.acourate.com/freedownload/Th ... K_v1.6.pdf

oder das

http://www.runeaudio.com/forum/rune-aud ... html#p6418

Letzteres als Beweis, dass es keines Mega-Rechners bedarf um das machen zu können.

Gruß

Uwe

Verfasst: 05.05.2015, 22:12
von frankl
Nova Auralis hat geschrieben: Im oben verlinkten Thread hatte mich Frank auf einen Beitrag von Martin hingewiesen. Diesbezüglich stellten sich mir folgende Fragen:

[...]

Ausschnitt aus der asound.conf:

Code: Alles auswählen

pcm.VIA_PCI {
   type hw
   card 2
   device 0
}

pcm.Dummy_HDMI {
   type hw
   card 0
   device 3
}

pcm.dmixer {
   type dmix
   ipc_key 1024
   slave.pcm "Dummy_HDMI"
   slave {
      periods 2
      period_size 4096
      buffer_size 8192
      rate 96000
      format S32_LE
      channels 2
   }
   bindings {
      0 0
      1 1
   }
}

pcm.!default {
   type plug
   slave.pcm "dmixer"
}
Ausschnitt aus der .brutefir_config:

Code: Alles auswählen

input "left_in", "right_in" {
        device: "alsa" { device: "pcm.!default"; ignore_xrun: true; };
};

output "left_out", "right_out" {
        device: "alsa" { device: "pcm.VIA_PCI"; ignore_xrun: true; };
};
Probiere ich die zitierten Konfigurationen aus, erhalte ich von BruteFIR allerdings eine Fehlermeldung, die da lautet:

Code: Alles auswählen

ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM pcm.!default
ALSA I/O: Could not open audio input "pcm.!default": No such file or directory.
Failed to init input device.
Failed to initialise digital audio interfaces.
Wo könnte das Problem liegen? Seltsam ist, dass BruteFIR mit "pcm.VIA_PCI" als Eingang problemlos arbeitet, bei "pcm.Dummy_HDMI" hingegen gibt es wieder die genannte Fehlermeldung. An der Art der Deklaration (anstatt dem gewöhnlichen Direktzugriff über "hw:...") scheint es also folglich nicht liegen zu können?
Hallo Jannis,

als Input musst Du natürlich Input (auch "capture") Devices nehmen. Außerdem musst Du das Signal an diesen Eingang bekommen! Welche Devices zum "playback" bereit stehen, findest Du mit 'aplay -l' raus, und welche für "capture" da sind, zeigt 'arecord -l'. (Alternativ kannst Du das auch in /proc/asound/card?/ sehen.) Wenn Du ein "capture" Device hw:0,0 hast, dann kannst Du damit in der Regel den Mikrofon-Eingang Deiner Soundkarte aufnehmen, aber nicht ein Signal, dass Du auf einen Ausgang schickst (es sei denn, Deine Soundkarte bietet per Hardware einen Loopback(!!!)). Genau dafür ist das Loopback ALSA device: Du kannst ein Signal rein schicken und wieder auslesen, eben wie der Name sagt.

Wenn Du (noch) nicht so viel von ALSA und so weiter verstehst, warum versuchst Du es nicht zuerst mal mit Lösungen, die bei anderen schon geklappt haben? Wenn Du zusätzlich mixen und upsamplen willst, kannst Du ja Dein dmixer Device vor das Loopback setzen.

Viele Grüße,
Frank

Verfasst: 06.05.2015, 20:30
von Nova Auralis
Hallo Frank,

ich danke dir wieder einmal für deine prompte hilfreiche Antwort! :cheers:

Meine Hoffnung war eben zuvor gewesen, dass in ALSA bereits standardmäßig die Möglichkeit implementiert sei, ein Audiosignal auch vor einem Ausgang abgreifen zu können. Dem ist ja scheinbar nicht so, dafür gibt es aber zumindest das virtuelle Loopback-Gerät, welches eine ähnliche Funktion bietet. Ich war deinem Hinweis nicht sofort gefolgt, weil es mich stets reizt eigene individuelle Lösungswege zu finden.

Nun will ich mein Vorgehen zur aktuell funktionierenden Konfiguration dokumentieren, falls jemand anders etwas Ähnliches plant. :wink:

Zuerst wird das virtuelle Loopback-Gerät (schickt wie gesagt ein eingehendes Audiosignal per Schleife zurück zu sich selbst auf ein jeweils zweites "Untergerät" und macht es damit abgreifbar) erzeugt. Dazu muss das ALSA Kernel-Modul "snd-aloop" geladen werden. Zum Testen kann man dies über den Befehl

Code: Alles auswählen

sudo modprobe snd-aloop
machen und dann per

Code: Alles auswählen

lsmod | grep aloop
überprüfen, ob es geklappt hat.

Ist alles in Ordnung, fügt man das Modul anschließend unter /etc/modules hinzu, damit es fortan beim Booten automatisch geladen wird.

Die genauere Deklaration, beispielsweise welchen Index das neue Gerät erhalten soll, geschieht über die "alsa-base.conf" unter /etc/modprobe.d/. Meine Konfiguration sieht wie folgt aus:

Code: Alles auswählen

options snd cards_limit=4
alias snd-card-0 snd-hda-nvidia
alias snd-card-1 snd-hda-intel
alias snd-card-2 snd-ice1724
alias snd-card-3 snd-aloop
options snd-hda-nvidia index=0
options snd-hda-intel index=1
options snd-ice1724 index=2
options snd-aloop index=3
Als nächstes folgt die Konfiguration von ALSA, entweder über die ".asoundrc" im Heimverzeichnis oder global über die "asound.conf" unter /etc/. Hier wieder beispielhaft meine persönliche Konfiguration:

Code: Alles auswählen

defaults.pcm.rate_converter "samplerate_best"

pcm.amix {
	type dmix
	ipc_key 68974
	slave.pcm "hw:3,0"
	slave {
		periods 4
		period_size 8192
		buffer_size 32768
		rate 192000
		format S32_LE
		channels 2
	}
	bindings {
		0 0
		1 1
	}
}

pcm.asnoop {
	type dsnoop
	ipc_key 68975
	slave.pcm "hw:3,1"
}

pcm.aduplex {
	type asym
	playback.pcm "amix"
	capture.pcm "asnoop"
}

pcm.!default {
	type plug
	slave.pcm "aduplex"
}
Nur als Hinweis, die oben gezeigte Konfiguration ist prinzipiell nicht vonnöten, stattdessen kann man die Wiedergabe-Software ebenso direkt auf "hw:Loopback,0" bzw. "hw:3,0" (in meinem Fall) ausgeben lassen.

Das duplizierte Audiosignal lässt sich jetzt von "hw:Loopback,1" (oder "hw:3,1") abgreifen. Im Folgenden der entsprechende Absatz aus meiner ".brutefir_config":

Code: Alles auswählen

input "left_in", "right_in" {
        device: "alsa" { device: "hw:3,1"; ignore_xrun: true; };
};

output "left_out", "right_out" {
        device: "alsa" { device: "hw:2,0"; ignore_xrun: true; };
};
Ich hoffe ich habe nichts wichtiges vergessen (oder Fehler gemacht), bei mir funktioniert die Wiedergabe über BruteFIR nun jedenfalls. Ich kann mich also endlich an den spannenden Teil - die Filtererstellung und -implementierung - begeben. :D

Beste Grüße,
Jannis

Verfasst: 06.05.2015, 20:54
von Buschel
Hallo zusammen,

schön zu sehen, dass hier Thread zu diesem Thema entsteht. In den letzten Tagen habe ich ebenfalls viel an meiner brutefir-config gearbeitet (siehe hier) und kann die Filter zur Laufzeit umschalten und prinzipiell auch per alsa-loop die Filterung von Rechner-internen Quellen -- bei mir vor allem kodi -- ausführen.

Allerdings läuft die neue Konfiguration nicht stabil. Sowohl bei 48 kHz als auch bei 96 kHz Samplingfrequenz bricht brutefir sporadisch mit buffer overflow oder underflow ab -- trotz "ignore_xrun: true;" für alle alsa I/Os. Ich habe die Konfiguration wieder ein wenig zurückgebaut, und es sieht für mich so aus, als ob die Abbrüche an der Verwendung der alsa-loop als capture-device liegen. Sobald ich dies auskommentiere, läuft brutefir wieder wie gewohnt. Im -- jetzt instabilen -- Normalbetrieb findet keine Wiedergabe über alsa-loop playback-device statt.

brutefir-config

Code: Alles auswählen

##
## DEFAULT GENERAL SETTINGS
##
float_bits: 64;			# internal floating point precision
sampling_rate: 96000;		# sampling rate in Hz of audio interfaces
filter_length: 512,128;		# blocksize, blocks (taps = blocksize * blocks)
overflow_warnings: true;	# echo warnings to stderr if overflow occurs
show_progress: false; 		# echo filtering progress to stderr
max_dither_table_size: 0; 	# maximum size in bytes of precalculated dither
allow_poll_mode: false; 	# allow use of input poll mode
modules_path: "."; 		# extra path where to find BruteFIR modules
monitor_rate: false; 		# monitor sample rate
powersave: true; 		# pause filtering when input is zero
lock_memory: true; 		# try to lock memory if realtime prio is set

##
## LOGIC 
##
logic: "cli" { port: 3000; };

##
## LAYOUT per channel
##
## usb in  >>-\         /---(convolve)-->> main
##             \       /        |
##             (+)-----       coef
##             /       \  
## loop in >>-/         \----(delay)---->> headphone
##                              |
##                            blocks
##

##
## OUTPUT 
##
## output 0,1,2,3: main L, main R, headphone L, headphone R
##
output "usb_out_main_L", "usb_out_main_R", "usb_out_hp_L", "usb_out_hp_R" {
  device: "alsa" { device: "usbaudio"; ignore_xrun: true;};
  sample: "S32_LE";
  channels: 18/0,1,6,7;
  delay: 0,0;
  maxdelay: -1;
  individual_maxdelay: -1,-1;
  mute: false,false;
  dither: false;
};

##
## INPUT
##
## input 0,1: usb audio
##
input "usb_in_L", "usb_in_R" {
  device: "alsa" { device: "usbaudio"; ignore_xrun: true;};
  sample: "S32_LE";
  channels: 18/4,5; 	# number of open channels / each channel
};
##
## input 2,3: loopback
##
#input "loop_in_L", "loop_in_R" {
#  device: "alsa" { device: "aloopc"; ignore_xrun: true;};
#  sample: "S32_LE";
#  channels: 2/0,1;	# number of open channels / each channel
#};

##
## COEFFICIENTS
##
## coef 0,1: music using excess phase correction (time domain correction)
##
coeff "coef_music_excphase_L" {
       filename: "./14-10-19/sink_10dB_BK/Cor1L96.dbl";
       format: "FLOAT64_LE";     # file format
};
coeff "coef_music_excphase_R" {
       filename: "./14-10-19/sink_10dB_BK/Cor1R96.dbl";
       format: "FLOAT64_LE";     # file format
};
##
## coef 2,3: music with minimum phase
##
coeff "coef_music_minphase_L" {
       filename: "./14-10-19/sink_10dB_BK/mpCor1L96.dbl";
       format: "FLOAT64_LE";     # file format
};
coeff "coef_music_minphase_R" {
       filename: "./14-10-19/sink_10dB_BK/mpCor1R96.dbl";
       format: "FLOAT64_LE";     # file format
};
##
## coef 4,5: movie with minimum phase (avoid audio delay for lip sync)
##
coeff "coef_movie_minphase_L" {
       filename: "./14-10-19/sink_10dB_BK_boost/mpCor1L96.dbl";
       format: "FLOAT64_LE";     # file format
};
coeff "coef_movie_minphase_R" {
       filename: "./14-10-19/sink_10dB_BK_boost/mpCor1R96.dbl";
       format: "FLOAT64_LE";     # file format
};

##
## FILTER
##
## filter 0,1: applying DRC (default: coef_music_excphase)
##
filter "filter_drc_L" {
  from_inputs: "usb_in_L";
  to_outputs: "usb_out_main_L";
  process: -1;
  coeff: "coef_music_excphase_L";
  delay: 0;
  crossfade: false;
};
filter "filter_drc_R" {
  from_inputs: "usb_in_R";
  to_outputs: "usb_out_main_R";
  process: -1;
  coeff: "coef_music_excphase_R";
  delay: 0;
  crossfade: false;
};
##
## filter 2,3: linear 
##
filter "filter_linear_L" {
  from_inputs: "usb_in_L";
  to_outputs: "usb_out_hp_L";
  process: -1;
  coeff: -1;
  delay: 64;	# sync with delay of excess phase filter (blocks/2, see filter_length)
};
filter "filter_linear_R" {
  from_inputs: "usb_in_R";
  to_outputs: "usb_out_hp_R";
  process: -1;
  coeff: -1;
  delay: 64;	# sync with delay of excess phase filter (blocks/2, see filter_length)
};
Die oben stehende Konfiguration wird instabil sobald ich

Code: Alles auswählen

## input 2,3: loopback
wieder aktiviere und die eingelesenen Daten als Input für die Filter verwende. :roll:

Die asound.conf sieht wie folgt aus

Code: Alles auswählen

#
# USB audio
#
pcm.usbaudio {
	type hw
	card 2
	device 0
	format S32_LE
	channels 18
}

#
# ALSA loopback (capture/playback)
#
pcm.aloopc {
	type hw
	card Loopback
        device 1
	format S32_LE
	channels 2
}

pcm.aloopp {
	type hw
	card Loopback
        device 0
}

pcm.loopcard {
	type plug
	slave.pcm "aloopp"
}
Abgesehen davon: Ist es auffällig, dass die buffersize für die RME-Karte "krumm" ist? Sie scheint sich aus 2^18 (default size für andere Soundkarten) geteilt durch Kanalanzahl (18) zu ergeben.

RME:

Code: Alles auswählen

$ cat /proc/asound/card2/pcm0p/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 18
rate: 96000 (96000/1)
period_size: 512
buffer_size: 14563

$ cat /proc/asound/card2/pcm0c/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 18
rate: 96000 (96000/1)
period_size: 512
buffer_size: 14563
alsa-loop:

Code: Alles auswählen

$ cat /proc/asound/card3/pcm1c/sub0/hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 96000 (96000/1)
period_size: 512
buffer_size: 262144
 
$ cat /proc/asound/card3/pcm0p/sub0/hw_params
closed
Falls ihr eine Idee habt, woran die Instabilität begründet sein könnte und was evtl. Abhilfe verschaffen könnte, bin ich für Tipps dankbar. :cheers:

Viele Grüße,
Andree

PS: Betriebssystem ist Ubuntu 14.04 mit low-latency Kernel.

Verfasst: 06.05.2015, 21:30
von Nova Auralis
Hallo,

wie bereits in Andrees Vorstellungs-Thread angemerkt, tritt bei mir ein ähnliches (oder identisches) Phänomen auf - und das obwohl ich noch keinerlei Filter anwende sowie ebenfalls aufgrund des "ignore_xrun" eigentlich die Over-/Underflows ignoriert werden sollten.

Hier ist meine vollständige ".brutefir_defaults":

Code: Alles auswählen

## DEFAULT GENERAL SETTINGS ##

float_bits: 32;             # internal floating point precision
sampling_rate: 192000;       # sampling rate in Hz of audio interfaces
filter_length: 8192,8;       # length of filters
config_file: "~/.brutefir_config"; # standard location of main config file
overflow_warnings: true;    # echo warnings to stderr if overflow occurs
show_progress: false;        # echo filtering progress to stderr
max_dither_table_size: 0;   # maximum size in bytes of precalculated dither
allow_poll_mode: false;     # allow use of input poll mode
modules_path: ".";          # extra path where to find BruteFIR modules
monitor_rate: false;        # monitor sample rate
powersave: true;           # pause filtering when input is zero
lock_memory: false;          # try to lock memory if realtime prio is set
sdf_length: -1;             # subsample filter half length in samples
safety_limit: 0.01;           # if non-zero max dB in output before aborting
convolver_config: "~/.brutefir_convolver"; # location of convolver config file

## COEFF DEFAULTS ##

coeff {
	format: "TEXT";     # file format
	attenuation: 0.0;   # attenuation in dB
	blocks: -1;         # how long in blocks
	skip: 0;            # how many bytes to skip
	shared_mem: false;  # allocate in shared memory
};

## INPUT DEFAULTS ##

input {
	device: "file" {};  # module and parameters to get audio
	sample: "S32_LE";   # sample format
	channels: 2/0,1;    # number of open channels / which to use
	delay: 0,0;         # delay in samples for each channel
	maxdelay: -1;       # max delay for variable delays
	subdelay: 0,0;      # subsample delay in 1/100th sample for each channel
	mute: false,false;  # mute active on startup for each channel
};

## OUTPUT DEFAULTS ##

output {
	device: "file" {};  # module and parameters to put audio
	sample: "S32_LE";   # sample format
	channels: 2/0,1;    # number of open channels / which to use
	delay: 0,0;         # delay in samples for each channel
	maxdelay: -1;       # max delay for variable delays
	subdelay: 0,0;      # subsample delay in 1/100th sample for each channel
	mute: false,false;  # mute active on startup for each channel
	dither: false;      # apply dither
};

## FILTER DEFAULTS ##

filter {
	process: -1;        # process index to run in (-1 means auto)
	delay: 0;           # predelay, in blocks
	crossfade: false;   # crossfade when coefficient is changed
};
Und meine ".brutefir_config":

Code: Alles auswählen

input "left_in", "right_in" {
        device: "alsa" { device: "hw:3,1"; ignore_xrun: true; };
};

output "left_out", "right_out" {
        device: "alsa" { device: "hw:2,0"; ignore_xrun: true; };
};

filter "left" {
        from_inputs: "left_in";
        to_outputs: "left_out";
        process: 0;
	coeff: -1;
};

filter "right" {
        from_inputs: "right_in";
        to_outputs: "right_out";
        process: 1;
	coeff: -1;
};
Bezüglich der krummen Buffergröße: Diese hat bei mir einen geraden Wert und trotzdem kommt es zu dem Fehler. Hieran wird es also wohl eher nicht liegen.

Code: Alles auswählen

access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 192000 (192000/1)
period_size: 8192
buffer_size: 32768
Der Vollständigkeit halber: Betriebssystem ist ein 64 Bit Linux Mint 17.1 (Xfce) mit Standard-Kernel

Beste Grüße,
Jannis

Verfasst: 07.05.2015, 08:22
von Buschel
Hallo Jannis,

zum einen beruhigt es mich, dass die Instabilität auch bei dir nachvollziehbar ist (andere Soundkarte, anderes Linux, anderer Kernel, andere Puffergrößen, noch schlankere brutefir-config), zum anderen heisst das es handelt sich wohl um ein tiefer liegendes Problem in alsa oder brutefir... :roll:

Ich versuch in den kommenden Tagen ein wenig im source code von brutefir zu wühlen. Vielleicht finde ich einen Hinweis...

Viele Grüße,
Andree

Verfasst: 07.05.2015, 23:47
von frankl
Hallo Jannis und Andree,

ich habe keine Erfahrung mit so einem Setup. Hier aber eine Frage, die Ihr Euch stellen könntet (ist aber vielleicht auch irrelevant):

Führt die ALSA-Konfiguration mit
defaults.pcm.rate_converter "samplerate_best"
vielleicht dazu, dass Eure CPU überlastet ist? (Prüfe zum Beispiel mit 'top'.) Ich habe bei dieser Einstellung mal 'aplay' und 'audacious' mit über 50% CPU-Last auf einem richtig schnellen Pentium gesehen.

Eine qualitativ gute und effiziente Samplerate-Konversion scheint mir ohnehin ein kritischer Punkt in diesem Ansatz zu sein.

Viele Grüße,
Frank

Verfasst: 08.05.2015, 08:21
von Buschel
Hallo Frank,

"top" zeigt mir an, dass -- je nach verwendeter Abtastrate (48 kHz / 96 kHz) -- noch 85-95% CPU-Zeit frei ("un") sind. Das schließt auch die Wiedergabe einer WAV-Datei über die Loopback ein, die eine andere Samplingfrequenz aufweist. Oder muss ich wegen der Multiprozessorumgebung auf andere Angaben achten?

Was ich probieren werde, ist, in brutefir anstatt alsa stdin zu verwenden.

Code: Alles auswählen

device: "file" {path: "/dev/stdin";}
Dann bediene ich brutefir über eine pipe mittels

Code: Alles auswählen

arecord -D aloopc -c 2 -f S32_LE -r 96000 | brutefir DRC_96k.conf
Damit ist auf jeden Fall Audio vorhanden. Inwiefern sich dieser Ansatz als stabiler erweist, muss ich erst über einige Probeläufe beobachten. Jannis, vielleicht ist das bei dir ja auch einen Versuch wert ...

Viele Grüße,
Andree

Verfasst: 08.05.2015, 14:30
von Nova Auralis
Hallo Frank,

bei Audiomaterial mit Abtastraten kleiner 192 kHz, sprich wenn das in ALSA eingestellte Resampling angewendet wird, steigt die Prozessorauslastung eines Kerns auf maximal 40 %, alle anderen drei Kerne bleiben unbelastet. Direkt mit 192 kHz Material bleibt die Auslastung unter 5 %. Ich bezweifle auch recht stark, dass mein Intel Core i5-3570k in irgendeiner Weise überlastet wird.

Ich könnte mir hingegen vorstellen, dass womöglich die Abstimmung der Buffer- und Periodengrößen essentiell für einen stabilen Betrieb sind! Wer kennt sich da mit den Zusammenhängen aus?

Falls ich mich nicht irre, sehen die Grundsätze hierbei wie folgt aus:

Der Buffer wird in eine definierte Anzahl Perioden unterteilt. Die Latenz wird maßgeblich durch die gesamte Buffergröße bestimmt, die Prozessorauslastung durch die Periodengröße. Ein Wiedergabe-Prozess schreibt solange Daten in den Buffer bis dieser voll ist und geht dann "schlafen". Am Ende jeder (durch die Hardware) gelesenen Periode wird ein Interrupt ausgelöst, wodurch der Prozess wieder "geweckt" wird und diese zuletzt gelesene Periode mit neuen Daten überschreibt. Wird also eine kleinere Periodengröße gewählt, so muss der Prozessor den Buffer häufiger nachladen/auffüllen, die Wahrscheinlichkeit für Aussetzer wird wohl geringer.

Ein übliches halbwegs ausbalanciertes Verhältnis ist die halbe Buffergröße als Periodengröße. Dies stellt auch gleichzeitig den empfohlenden Mindestwert (zwei oder mehr Perioden im Buffer) dar, weil ansonsten womöglich noch nicht ausreichend neue Daten in den Buffer geladen worden sind, bevor der nächste Interrupt geschieht.

Dieses Szenario, wenn der Buffer während der Wiedergabe nicht schnell genug mit Daten befüllt wird, nennt sich Underflow oder Underrun. Zum Overflow oder Overrun kommt es dagegen während der Aufnahme, wenn die Daten aus dem Buffer nicht schnell genug gelesen werden und bereits wieder überschrieben wurden.

Ich bitte gegebenenfalls um Ergänzung oder Korrektur. :wink:

Ansonsten, was lässt sich nun daraus schließen? Wie sollten Perioden- und Buffergröße optimalerweise (Prozessorauslastung und Latenz erst einmal außen vor gelassen) gewählt werden, damit es zu keinen Over-/Underflows kommt? Grundsätzlich ja eigentlich der Buffer unterteilt in genügend Perioden, nur wie sieht es mit der gesamten Buffergröße aus? Was ist beim Zusammenspiel hiervon mit der Filterlänge (in BruteFIR) sowie Partitionierung dieser zu beachten?

Nachtrag: In meinem Fall kommt es übrigens regelmäßig zum Overflow!

Beste Grüße,
Jannis

Verfasst: 08.05.2015, 20:45
von Buschel
Hallo Jannis,

läuft die von mir oben beschriebene Lösung per arecord / stdout / stdin / brutefir bei dir genauso instabil?

Viele Grüße,
Andree

Verfasst: 09.05.2015, 18:27
von Buschel
Hallo,

die Lösung über arecord -> stdio -> brutefir ist (in meinem Setup) auch instabil. Allerdings kann man mit Setzen der Option

Code: Alles auswählen

link: false;
für jedes einzelne verwendete alsa-device in der brutefir-config den Abbruch von brutefir vermeiden, wenn für das loop-device gleichzeitig auch

Code: Alles auswählen

ignore_xrun: false;
gesetzt ist. Bei einer solchen Konfiguration bekomme ich Fehlermeldungen auf der Konsole, das Playback läuft aber weiter. Allerdings sind dann Störgeräusche wahrnehmbar.

Für mich sieht das so aus, als ob der Fehler irgendwo in alsa oder der alsa-loop liegt. :roll:

Viele Grüße,
Andree

Verfasst: 02.08.2015, 13:54
von Buschel
Hallo zusammen,

zwar läuft es jetzt erst seit einigen Stunden (inkl. gewollten Neustarts) stabil, aber erwähnenswert ist es dennoch: Es scheint so, als ob pulseaudio das Problem verursacht hat. Ohne pulseaudio funktioniert die alsa-loop bisher ohne die beobachteten Probleme (under-/overflow oder auch Störgeräusche).

Viele Grüße,
Andree

Verfasst: 03.08.2015, 21:04
von Daihedz
Hallo Andree
Buschel hat geschrieben:... pulseaudio das Problem ...
Pulseaudio braucht es für eine Minimal-ALSA-Lösung nicht. Ich entferne es (nebst anderem Ballast) standardmässig in all meinen Linux-Audio-Setups.

Was ich auch noch anders habe in meinen Brutefir-Configs:

float_bits: 64; # internal floating point precision
lock_memory: true; # try to lock memory if realtime prio is set
powersave: false; # pause filtering when input is zero
Anders Torger (in der Brutefir-Readme) hat geschrieben:If there is any sound card used for input or output (or any other sample-clock dependent device), BruteFIR will automatically set its delay-sensitive processes to realtime priority, thus you will typically need to run the program as root. To maintain realtime performance, it is important that there is no memory belonging to the program in the swapfile, thus all memory must be locked to RAM. This is done if lock_memory is set to true. Note that the memory is never locked when realtime priority is not set (that is when there are only files used for input and output). Warning: there seems to be a bug in the Linux kernel which makes the shared memory to be locked one time for each process, meaning that when lock_memory is set to true, BruteFIR will seem to consume a lot more memory than it should. Also, it makes of course no sense to lock memory if your system does not have a swap activated. Due to this issue, the best thing to do is to have a system with no swap and avoid locking the memory.
Der zitierte Kernel-Bug wird zwischenzeitlich wohl behoben worden sein. Dennoch habe ich im Zeitalter der billigen RAM-Gigabytes standardmässig auch keine Swap-File mehr auf meinen Audio-Linuxen.

Gefaltete Grüsse
Simon

Verfasst: 20.08.2015, 17:58
von Buschel
Hallo mal wieder,

ich verzweifle so langsam. Einige Tage lief alles bestens, und ich habe ganz nach der Prämisse "never change a running system" auch keine Updates mehr gefahren. Irgendwann fingen die sporadischen Abbrüche wieder an, heute wieder extrem heftig. :(

@Simon: lock_memory ist und war bei mir aktiviert, powersave habe ich heute probehalber deaktiviert. Es macht keinen Unterschied.

Ich fummele ja ab zu gerne am Computer herum, aber für den gedachten Zweck muss die ganze Mimik laufen, wenn es einmal eingerichtet ist. Sollte ich von ubuntu Abstand nehmen? Wenn ja, was ist die bessere und schlankere Alternative (brutefir, kodi und ein Browser sollen laufen)?

Ernüchterte Grüße,
Andree