How to mix S/PDIF input and PCM Out (to hear PCM and S/PDIF simultaneously)?

D

*Dark Dragon*

Guest
I want to hear PCM Out and S/PDIF In simultaneously from my analog speakers.

In other words what I want is this:
PCM Out + plughw:0,1 -> hw:0,0

plughw:0,1 is my S/PDIF stereo input (sound from external device).
hw:0,0 is my analog stereo output (my speakers).
PCM Out represents stereo sounds from all programs in my computer.

At first I thought mixing sounds from external device with sounds from my computer and listening to the result on my speakers will be easy, it seems pretty natural thing to do... but I can't find a solution. If somebody can suggest something, I will really appreciate it.

My sound card is M-Audio Audiophile 192 and I use Debian Linux.


Summary of what I actually achieved at the moment

With ALSA and OSS (without pulseaudio) I can get:
plughw:0,1 -> hw:0,0
or
PCM Out -> hw:0,0

With pulseaudio and jack I'm able to get only this at the moment:
PCM Out -> hw:0,0


What I have tried to achieve the goal with ALSA

Hypothetically, by writing special asound.conf it may be possible to get what I want with ALSA. I tried to write one based on the example (forum.xbmc.org/showthread.php?tid=96138), but could not get it to work, even after reading ALSA documentation (alsa-project.org/main/index.php/Asoundrc).

Here is my not working asound.conf in case somebody can help to fix it: (science.su/stuff/log/asound.conf) - instead of mixing S/PDIF In and PCM Out it just "mutes" PCM Out and that's it. Here are also sreenshot of alsamixer -V all (science.su/stuff/sreenshot/alsamixer_-V_all.jpg) and output from amixer (science.su/stuff/log/amixer.txt) aplay -l (science.su/stuff/log/aplay.txt), cat /proc/asound/devices (science.su/stuff/log/devices.txt).

Note: I need stereo sound, so selecting S/PDIF In (in alsamixer called "IEC958 In") for one channel, and PCM Out for the other is not an option.


What I have tried to achieve the goal with JACK

At this moment I think JACK may help to achieve my goal, but unfortunately when I run qjackctl I see only analog inputs/outputs:
capture_1, capture_2 (that's plughw:0,0)
playback_1, playback_2 (that's hw:0,0)
...and do not see controls for plughw:0,1 (S/PDIF stereo input) and hw:0,1 (S/PDIF stereo output). PCM Out is missing too. I have no idea how to add missing inputs/outputs to JACK, reading the documentation and googling did not help. Tab "MIDI" in qjackctl is empty, and tab "ALSA" contains only MIDI devices.

(I omit what I have tried with OSS4 and PulseAudio because I see no potential way to achieve what I want with them - please correct me if I'm wrong)
 


The solution

It seems that JACK is my only option. But the fact that PCM Out does not exist in JACK is a problem. Despite the fact that my sound card costs about $200 it doesn't support hardware mixing. Fortunately, I was able to solve this by using ALSA JACK plugin.

About my other problem with JACK... After careful reading of the documentation and Googling it turns out JACK works exactly as it should. I'm supposed to add non-default devices manually - either by creating one big multichannel ALSA device, or by using alsa_in/alsa_out - these two didn't work for me too well no matter what period size I have used, so I created multichannel ALSA device. What confused me in the first place is the fact that nearly everywhere people talk about this only in context of "unifying" multiple sound cards - but in reality this is necessary to use multiple ALSA devices in one card too.

By the way, I do not think anymore that it is possible to solve this without JACK. ALSA does not allow to mix input(s) with output(s): in alsamixer it is possible to reroute input to output, but impossible to mix them; in asound.conf it is possible to attempt to do so, but the result will be non-working ALSA device. PulseAudio have similar limitation. So, JACK is the only way to solve this problem.

Now, I will describe the solution. I tried many things, but all other configurations/method either gave me bad sound or worked similarly in practice, but were more complex. So I will give here the simplest solution that worked for me (and mention some alternatives which are likely to work at least for some people). I use Debian Testing, so some things I mention are Debian-specific. It should not be too hard to do the same in other distributions.


Install JACK
apt-get install qjackctl jackd2


Configure ALSA
Run this command:
sudo apt-get install libasound2-plugins
Here is my /etc/asound.conf (science.su/stuff/linux/sound/jack/asound.conf), you can put its contents in ~/.asoundrc - but /etc/asound.conf is better place because it is system-wide. As you can see, it's relatively simple. Device "all" is intended for JACK, and !default - for all non-JACK applications. It is important that the !default is of type plug and not jack, otherwise you will get all sorts of strange problems. You can easily adapt my asound.conf to your needs - it is hopefully obvious how to add or remove audio devices and channels. If not, read the documentation (alsa-project.org/main/index.php/Asoundrc).

IMPORTANT NOTE: If your sound card is capable of hardware mixing, you do not need !default section with ALSA JACK plug-in to hear sound from non-JACK applications. If you are unsure what your card is capable of, run:
cat /proc/asound/card0/pcm*/info | grep count
If at least some devices have more than 1 subdevice, your card is capable of hardware mixing. If hardware mixing is available on your default channels, you can remove !default section from my example of asound.conf.


Only problem in my asound.conf is that analog input (typically microphone) cannot be used as mono if you specified stereo analog input like me. Another strange thing is that I get a lot of XRUNs in JACK but they do not affect sound quality in my case, so I ignore them.

Alternative ALSA configuration (NOT recommended!)
It is possible to write asound.conf without ALSA JACK plug-in, but in my case this resulted in bad sounds with frequent click-like artifacts on inputs despite very large buffer_size (sometimes few artifacts per minute, sometimes one artifact per few minutes) even after upgrade to PF kernel (later I'll explain what is it). No surprise here, because JACK must use your audio devices as directly as possible and this is not the case here. If you want to try this anyway for whatever reason, please see my /etc/asound.conf without ALSA JACK plug-in (science.su/stuff/linux/sound/jack/without_alsa_jack_plugin/asound.conf). It is more complex than the first one, but I tried to make it as readable as possible. Before trying it, make sure that you are using the same period_size and periods in JACK and asound.conf. I leave this alternative configuration as an example to learn from (you can see how to use various types in asound.conf, how to upmix mono to stereo, etc.).


Configure JACK
Here is screenshot of my settings in qjackctl (science.su/stuff/linux/sound/jack/qjackctl_settings.jpg). Most important settings are "Realtime", "Input device" and "Output device". Everything else is just an example of working setup.


Upgrade to better kernel
It is good idea to try to migrate to RT kernel (eventually vanilla kernel will include similar real-time support, but for foreseeable future you have to use patched kernel if you want acceptable audio latency with no artifacts, especially from audio input(s) ). To try RT kernel in Debian Testing or higher you need just run this command (I assume you need NVidia driver; if not, install whatever driver you need instead):

sudo apt-get install linux-image-3.4-trunk-rt-amd64 linux-headers-3.4-trunk-rt-amd64 nvidia-kernel-dkms

If RT kernel works for you, feel free to skip the rest of this message. With RT kernel you can hear perfect low-latency sound. But unfortunately many NVidia cards do not work with RT kernels, and mine was one of them (GeForce GTX 295), so I couldn't use RT.

Note: with vanilla kernel I encountered click-like artifacts few times per minute in both analog and digital inputs - this was unacceptable, so vanilla kernel did not work for my purpose. If it works for you and you are OK with relatively high audio latency (buffer) you have to tolerate for acceptable sound, you obviously do not need to change your kernel.

NVidia driver in Debian already contains modifications to work with 3.4 RT kernel, you do not need to modify it, but unfortunately it may give you black screen instead of your graphical interface. In this case, you have to uninstall RT kernel and try something else, for example PF-kernel (pf.natalenko.name). Author does not provide deb files, but links to somebody's site who does (kernel.night-leshiy.ru) - this site written in non-English language, but whatever language it is, you do not need to understand it, just download deb files with pf kernel and its headers and install them with:

sudo dpkg -i linux-*-pf*.deb

PF kernel contains BFS scheduler, and in my Xeon-based quad core workstation with 8 hardware threads (so the OS sees it as 8 CPUs) it reduced worse-case latencies of real-time processes (like JACK) from hundreds of milliseconds to few milliseconds (in my case less than 2ms). This is of course looks as very bad result if you compare with RT kernel (with worst-case latencies of real-time processes within 10-30 microseconds range) but MUCH better than vanilla kernel. Personally I use 128 buffer_size with 2 periods - that's ~5ms latency; in my case this is enough to prevent any artifacts in the sound after few hours of testing. With RT kernel even better results should be possible.

Note: Yes, I know BFS is not the best scheduler, but it works much better then vanilla scheduler if you want low latency and RT kernel does not work for you. In case you want as small latencies as possible without RT kernel, there are improved BFS with O(1) complexity instead of O(n), and probably even better scheduler - RIFS. You can find them here (code.google.com/p/rifs-scheduler/downloads/list) if you up to compiling your own kernel. If you are, install kernel-package and read this howto (vanilja.org/kernel).

Hope my experience will be useful to somebody.
 

Staff online

Members online


Latest posts

Top