Page 1 of 1

[SOLVED] How to mix S/PDIF input and PCM Out

Posted: Sat Jul 14, 2012 8:46 pm
by *Dark Dragon*
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.
hw:0,0 is my analog stereo output.
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 knows what else to try, please help.

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, but could not get it to work, even after reading ALSA documentation.

Here is my not working asound.conf in case somebody can help to fix it: 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 and output from: amixer, aplay -l, cat /proc/asound/devices.

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)

Re: How to mix S/PDIF input and PCM Out

Posted: Sun Jul 15, 2012 3:28 pm
by Capoeira
first, this
*Dark Dragon* wrote: PCM Out represents stereo sounds from all programs in my computer.

doesn't exist in jack. every program is represented and connects seperatly in jack. this, if the program has a jack output.


second, this should be easy to achive in jack. but, you digital ins/outs should appear in jack. that's the problem.
what do you have in the Channels I/O field in qjackctl? perhaps you limited the channels there. this should read "default"



as you said, this can be achieved with alsa and .asoundrc, too. but I never wrote one.

Re: How to mix S/PDIF input and PCM Out

Posted: Fri Jul 20, 2012 12:03 pm
by *Dark Dragon*
> [PCM Out] doesn't exist in jack. every program is represented and connects seperatly in jack.
It seems that JACK is my only option but the fact that PCM Out does not exist in JACK (and cannot exist) 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.

> second, this should be easy to achive in jack. but, you digital ins/outs should appear in 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.

> as you said, this can be achieved with alsa and .asoundrc, too
I do not think so anymore. ALSA does not allow to mix input(s) with output(s). It is possible to attempt to do so, but the result will be non-working ALSA device. PulseAudio have similar limitation.

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 (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.

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. 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 JACK settings in qjackctl. 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 to get 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. Author does not provide deb files, but links to somebody's site who does - 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 if you up to compiling your own kernel. If you are, install kernel-package and read this howto.

Hope my experience will be useful to somebody.

Re: [SOLVED] How to mix S/PDIF input and PCM Out

Posted: Tue Nov 13, 2012 12:12 am
by danboid
Hi Dark Dragon!

Thanks for your guide - I'm trying to get my USB SPDIF input working under JACK and your postings here are the only relevant instructions for this I can find although I've not had any luck so far following them and using a slightly modified version of your asound.conf. Depending on when I plug in my device, it gets enumerated as either hw:1 or hw:2 so my first question is can I use the device name string in asound.conf instead of defining it with the unpredictable (for USB users) hw:x format?

My device is a Startech USB audio device based on the C-Media CM6206. When I run alsamixer and switch to viewing the capture ports of the cm6206 there are 4 capture channels - PCM, Line, Mic and S/PDIF In but under JACK I only get 2 capture ports which are the L and R analogue mic input channels. I can also see the light emitting from the S/PDIF out port so I am confident the S/PDIF should work but hopefully under JACK and not just ALSA.

It seems your SPDIF is seen as an ALSA subdevice but mine isn't. I tried using your ALSA config but replacing all the 'card 0's with 'card 2's then replacing the 'hw:0' and 'hw:0,1's with 'hw:2's or doing the same but card 1 and hw:1 instead but that didn't work - I didn't get any 'all' option under the JACK input / output dropdowns (after rebooting/ restarting ALSA of course and checking the right hw:x device had been picked).

arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Intel [HDA Intel], device 0: ALC262 Analog [ALC262 Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Loopback [Loopback], device 0: Loopback PCM [Loopback PCM]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
card 1: Loopback [Loopback], device 1: Loopback PCM [Loopback PCM]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
card 2: Device [USB Sound Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
default:CARD=SB
HDA ATI SB, ALC268 Analog
Default Audio Device
sysdefault:CARD=SB
HDA ATI SB, ALC268 Analog
Default Audio Device
front:CARD=SB,DEV=0
HDA ATI SB, ALC268 Analog
Front speakers
surround40:CARD=SB,DEV=0
HDA ATI SB, ALC268 Analog
4.0 Surround output to Front and Rear speakers
surround41:CARD=SB,DEV=0
HDA ATI SB, ALC268 Analog
4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=SB,DEV=0
HDA ATI SB, ALC268 Analog
5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=SB,DEV=0
HDA ATI SB, ALC268 Analog
5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=SB,DEV=0
HDA ATI SB, ALC268 Analog
7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
default:CARD=Device
USB Sound Device, USB Audio
Default Audio Device
sysdefault:CARD=Device
USB Sound Device, USB Audio
Default Audio Device
front:CARD=Device,DEV=0
USB Sound Device, USB Audio
Front speakers
surround40:CARD=Device,DEV=0
USB Sound Device, USB Audio
4.0 Surround output to Front and Rear speakers
surround41:CARD=Device,DEV=0
USB Sound Device, USB Audio
4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Device,DEV=0
USB Sound Device, USB Audio
5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Device,DEV=0
USB Sound Device, USB Audio
5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Device,DEV=0
USB Sound Device, USB Audio
7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
iec958:CARD=Device,DEV=0
USB Sound Device, USB Audio
IEC958 (S/PDIF) Digital Audio Output
default:CARD=Loopback
Loopback, Loopback PCM
Default Audio Device
sysdefault:CARD=Loopback
Loopback, Loopback PCM
Default Audio Device

cat /proc/asound/devices
1: : sequencer
2: [ 0- 3]: digital audio playback
3: [ 0- 0]: digital audio playback
4: [ 0- 0]: digital audio capture
5: [ 0] : control
6: [ 1- 1]: digital audio playback
7: [ 1- 1]: digital audio capture
8: [ 1- 0]: digital audio playback
9: [ 1- 0]: digital audio capture
10: [ 1] : control
11: [ 2- 0]: digital audio playback
12: [ 2- 0]: digital audio capture
13: [ 2] : control
33: : timer

If anyone can explain how I'd convert that into a working ALSA config file to get access to my SPDIF input under JACK I'd be very grateful!

Re: [SOLVED] How to mix S/PDIF input and PCM Out

Posted: Tue Nov 13, 2012 12:46 am
by danboid
I've also tried keeping the 'card 0' lines as is as well as using 'card 1' and adjusting the 'hw:x' bits to 'hw:1' in the ALSA config - no go.

We should adjust the 'card x' lines so that x = whatever card number matches the SPDIF device as displayed when you do a 'arecord -l' (lowercase l) right?