Saturday, January 23, 2016

Sound in Slackware64 current (14.2)

UPDATE:
I installed Plasma 5.2 and now it is possible to change the output device from the System Settings > Multimedia window. Still is not a clean process but, it is cleaner than to copy and delete the asound.conf file. The procedure consisted in just to move upwards the HDMI output device in the Audio Playback option from the Audio and Video section. In my case the sub device connected to the HDMI port is the 0,7 (HDMI 2). Then, this devise also should be selected as profile in the Audio Hardware Setup tab. I tried to make a new Activity with the new configuration, but it didn't work due to the fact that all the activities share the same System Configuration, if you change something in one, it will also change in the others. Also, the configuration file snd-hda-intel.conf is not needed anymore.
---

After installing Slackware64-current (2015.12.29) I did not have sound neither in the speakers nor in the headphones. So I checked how ALSA had detected the soundcards:

$ cat /proc/asound/cards
0 [HDMI ]: HDA-Intel - HDA Intel HDMI
               HDA Intel HDMI at 0xb211c000 irq 50
1 [PCH  ]: HDA-Intel - HDA Intel PCH
               HDA Intel PCH at 0xb2118000 irq 47

So, ALSA configured the HDMI card as first device and it used it as default. Connecting the HDMI port to a TV the sound flew from the TV speakers. The problem was solved by switching the name of both cards in the file /etc/modprobe.d/snd-hda-intel.conf


/etc/modprobe.d/snd-hda-intel.conf
options snd-hda-intel model=auto

alias char-major-116 snd

alias snd-card-0 snd-hda-intel
alias snd-card-1 snd-hda-intel

options snd-hda-intel id=PCH index=0

options snd-hda-intel id=HDMI index=1
#

After rebooting, the sound started to work properly in the speakers and headphones. Auto-mute mode worked fine as well. 

$ cat /proc/asound/cards
0 [PCH   ]: HDA-Intel - HDA Intel PCH
                HDA Intel PCH at 0xb2118000 irq 47 
1 [HDMI ]: HDA-Intel - HDA Intel HDMI
                HDA Intel HDMI at 0xb211c000 irq 50

In the other hand, connecting the HDMI port did not change the sound output. In other words, although there was video in the TV, the sound came out from the computer's speakers or headphones.  
The solution of this problem is not trivial. Some people try to solve it changing the default card every time they use a different card. Although it seem that it is possible to build a script to overwrite the setting (defined in /etc/asound.conf) i found this solution too dirty. Instead, I followed the idea of cloning the sound from one card to the another, so, always in both cards (PCH and HDMI) will sound the same audio and will be possible to just mute the computer's speakers when it will be connected to a TV.

After a couple of hours looking for a solution and a lot of try and error, I found a good reference to follow. Finally, The solution consisted in configure ALSA to create a virtual device which route the audio to both devices. Also, the configuration solves the error that occurs when multiple applications try to access to the virtual card at the same time. The configuration is made in /etc/asound.conf :

# /etc/asound.conf
pcm.PCH {
        type hw
        card 0
        device 0 }
        
ctl.PCH {
        type hw
        card 0
        device 0 }        

pcm.HDMI {
        type hw
        card 1
        device 7 }     

ctl.HDMI {
        type hw
        card 1
        device 7 }        

pcm.PCHDmixed {
   type dmix
   ipc_key 1024
   ipc_key_add_uid false
   ipc_perm 0666
   slave {
       pcm "PCH"
       period_time 0
       period_size 2048
       channels 2
    }
    bindings {
       0 0
       1 1
    }
}

pcm.HDMIDmixed {
   type dmix
   ipc_key 2048
   ipc_key_add_uid false
   ipc_perm 0666
   slave {
       pcm "HDMI"
       period_time 0
       period_size 2048
       channels 2
    }
    bindings {
       0 0
       1 1
    }
}

pcm.both {
    type route;
    slave.pcm {
        type multi;
        slaves.a.pcm "HDMIDmixed";
        slaves.b.pcm "PCHDmixed";
        slaves.a.channels 2;
        slaves.b.channels 2;
        bindings.0.slave a;
        bindings.0.channel 0;
        bindings.1.slave a;
        bindings.1.channel 1;
       
        bindings.2.slave b;
        bindings.2.channel 0;
        bindings.3.slave b;
        bindings.3.channel 1;
    }
   
    ttable.0.0 1;
    ttable.1.1 1;
   
    ttable.0.2 1; 
    ttable.1.3 1; 
}

pcm.!default {
        type  plug
        slave.pcm "both"}
        
ctl.!default {
        type  hw
        card PCH}
#

The sections pcm.PCHDmixed  and pcm.HDMIDmixed are needed to face the problem with concurrent sound from different applications. The section pcm.both defines a new PCM consisting of 4 channels, two from the PCH card and two from the HDMI card. PCM is a stereo card and, I guess, HDMI is it as well (at least the TV is it). The magic is finally done by routing the audio channels to the correct speakers (physical channels). This is done by the ttable sentence. It took me a bit long to understand the logic behind but finally I understood the syntax as follow:

ttable.speaker.channel gain

Here, the speakers are coded as: 0 = front left; 1 = front right; 2 = rear left; 3 = rear right;  4 = center; 5 = subwoofer. Meanwhile, channel is the number of the binding connected to an audio channel. Finally, gain is a factor applied to modify the loudness of the channel (0.5 -> 50%).

In between I found that ALSA stores it last parameters in the file /var/lib/alsa/asound.state (there is a link in /etc/) which is written when the computer shutdown. There is a method to temporarily remove it in this link.

I did a fast check connecting a TV and it works fine. But, I think, it still need to be tested with details.

Update: Skype reported that there is not mic available. It is needed to configure a capture channel with dmix. 

No comments: