Thursday, January 21, 2010

pulseaudio, a wii, and the 10-dollar tvcard

So I've got a saa7134 tvcard (specifically a kworld tv-terminator) that was always troublesome to get working but worked when it worked (as in it's a PITA to get working but is stable thereafter). Over the years, the way to use this card has changed as the driver got fixed up more and as linux itself changed. MPlayer seems more able to control the card properly than tvtime, which gets stuck in some less-than acceptable options. Well anyway, the most troublesome part of this card is that if you want low latency, you have to tell the driver to do this and have to run another program to reroute audio from the tvcard to your soundcard - for whatever reason mplayer cannot do this and so... well thats where things get interesting. For reference, my mplayer command is:
mplayer tv:// -tv input=2:norm=1:immediatemode=1:amode=1 -vf pp=lb
This is for svideo-in/720p and low latency stereo mode that has a linear blur applied. The blur fixes jumpy video which has some analog source or something.

Now for the sound:
After opening mplayer you must do either something like (the old way which happened to work with low latency)
arecord -D hw:1,0 -r 32000 -c 2 -f S16_LE | aplay -N -R 0 -c 2 -r 32000
Or, since todays linux uses pulseaudio, you can use module-loopback. There are a bunch of other ways you could redirect the audio from the tvcard to your system's soundcard but the problem is that they are usually full of latency (by anywhere from .5 seconds to 2). The two options I propose are not and are essential for any kind of gaming where the time from button press to sound being heard is critical.

Are you ready for how to do it with pulseaudio? Well, at first it seems easy, and probably will be for most of you - simply
pacmd load-module module-loopback
It autodetected things pretty good, I used pavucontrol for some other slight configuration. But there was one problem, things sounded ok but there was this.... pausing. The default sampling rate on my pulse configuration is 48000hz and there seems to be a problem with all of the parameters of my cheap card and autodetection. On inspection of pacmd list-sources, I confirmed pulse had set itself to 48000hz while the hardware/alsa driver only genereted 32000... that means every second, there were 16 thousand samples completely missing which just somehow turned out to be zeroed (thus the pausing, there was logically no audio being played each pause as the pcm audio data was zeros). The solution was then to specify the 32000 to the module-alsa-source module for the tvcard. The exact command was
pacmd load-module module-alsa-card device_id="1" name="pci-0000_09_01.0" card_name="alsa_card.pci-0000_09_01.0" tsched=yes ignore_dB=no rate=32000
I derived these parameters from a pacmd list-modules, looking for the argument line who's card_name parameter matched the pci id of tvcard (you can see these using paman or pacmd list-sources). Note btw that before you execute the above command specifying rate, you must unload the module-alsa-card who has current ownership of the card (you use the index of the module to pacmd unload-module)

Also note that since things are going through pulse, this audio is now subject to the pulseaudio processing chain, and more specifically, the equalizer sink, and still with acceptable latency.

That's all folks - happy audio trails.