User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Jan 13, 2018 10:23 am

Hi,

Way back in Nov 2016, I posted a query about playing two mp3 files simultaneously through two independent USB audio adaptors for my local Model Town. I got it to work, see viewtopic.php?f=38&t=164784&p=1066454#p1066454, but then fell at the next hurdle because all the adaptors that I could source at that time had the same ID, so it was impossible to determine which was which when directing the audio to the right channel. In the end, I abandoned using a Pi Zero and used a Pi 3 instead because it had an independent audio jack that could be identified and the USB adaptor then stayed on the same channel.

However.... All in the garden is not rosy. During the summer season the system began to suffer from cross-talk and very noticeable hum; a problem that I put down in part at least to the fact that the original 12 V Power Brick for the audio amps failed and the new one is noisy compared to the old one. I've now filtered this and the problem is much reduced, but is still apparent. The real problem seems to be that the Pi itself introduces a hum loop and the audio is modulated onto the hum and so appears on both channels. In an effort to solve this once and for all I bought a new set of USB audio adaptors from a different source and joy of joys :D they have a different ID to the originals.

My problem now is how to translate the information from dmesg, lsusb and aplay -l to allow me to discover the hw: numbers for the two devices programatically.

With both adaptors plugged into this desktop machine, here is the output of lsusb:

Code: Select all

terry@OptiPlex:~$ lsusb
Bus 002 Device 006: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller
Bus 002 Device 005: ID 045e:0084 Microsoft Corp. Basic Optical Mouse
Bus 002 Device 004: ID 046a:0023 Cherry GmbH CyMotion Master Linux Keyboard G230
Bus 002 Device 003: ID 046d:09a2 Logitech, Inc. QuickCam Communicate Deluxe/S7500
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 8086:0808 Intel Corp. 
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
The C-Media device 0d8c:013c is one adaptor and 8086:0808 is the other.

Here is aplay -l:

Code: Select all

terry@OptiPlex:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC269VB Analog [ALC269VB Analog]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0                                                                                                                                   
card 4: Device_1 [USB PnP Sound Device], device 0: USB Audio [USB Audio]                                                                                       
  Subdevices: 1/1                                                                                                                                              
  Subdevice #0: subdevice #0

As you can see there is no clue as to which [USB PnP Sound Device] is the C-Media one and which is the intel one.

Here is dmesg:

Code: Select all

terry@OptiPlex:~$ dmesg | grep PnP
[    0.107560] pnp: PnP ACPI init
[    0.108176] pnp: PnP ACPI: found 6 devices
[ 7168.666002] usb 1-1.3: Product: USB PnP Sound Device
[ 7168.686080] input: C-Media Electronics Inc.       USB PnP Sound Device as /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3/1-1.3:1.3/0003:8086:0808.0004/input/input15                                                                                                                                                      
[ 7168.744309] hid-generic 0003:8086:0808.0004: input,hidraw3: USB HID v1.00 Device [C-Media Electronics Inc.       USB PnP Sound Device] on usb-0000:00:1a.0-1.3/input3                                                                                                                                                      
[ 7174.537970] usb 2-1.7: Product: USB PnP Sound Device
[ 7174.558015] input: C-Media Electronics Inc.       USB PnP Sound Device as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.7/2-1.7:1.3/0003:0D8C:013C.0005/input/input16                                                                                                                                                      
[ 7174.616030] hid-generic 0003:0D8C:013C.0005: input,hidraw4: USB HID v1.00 Device [C-Media Electronics Inc.       USB PnP Sound Device] on usb-0000:00:1d.0-1.7/input3
Suddenly, they both seem to be C-media devices!

What I can't quite see is how I can extract from dmesg and / or lsusb the link that tells me the Card and Subdevice numbers that I can use to play the file using aplay or mpg321. The output from lsusb seems to bear no relation to the Card numbers and the output from dmesg is frankly gobblygook to me.

Can anyone help with the necessary alchemy?

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sun Jan 14, 2018 6:25 pm

Replying to myself.

There's been some discussion about this on my local LUG Mailing List, but I've had problems posting the output of aplay -l after a reboot, so here it is:

Code: Select all

terry@OptiPlex:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 1: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: PCH [HDA Intel PCH], device 0: ALC269VB Analog [ALC269VB Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 4: Device_1 [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
Note that the two USB Audio Adaptors are now in different Card numbers.

AJB2K3
Posts: 213
Joined: Sun Aug 11, 2013 3:25 pm

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Fri Jan 19, 2018 8:47 pm

TerryC65 wrote:
Sun Jan 14, 2018 6:25 pm
Replying to myself.

There's been some discussion about this on my local LUG Mailing List, but I've had problems posting the output of aplay -l after a reboot, so here it is:

Code: Select all

terry@OptiPlex:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 1: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: PCH [HDA Intel PCH], device 0: ALC269VB Analog [ALC269VB Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 3: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 4: Device_1 [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
Note that the two USB Audio Adaptors are now in different Card numbers.
there used to be a way to mk-node and force a new nodename for each device then point the software to the separate nodes but I can't remember how I did this.
I know I used a similar trick to get GPSD to work.
Back in the old days, we were smarter then the technology.
Nowadays technology makes us look like villages fools in front of the children!

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Jan 20, 2018 7:44 am

AJB2K3 wrote:
Fri Jan 19, 2018 8:47 pm
there used to be a way to mk-node and force a new nodename for each device then point the software to the separate nodes but I can't remember how I did this.
I know I used a similar trick to get GPSD to work.
The local LUG Mailing List denizens have pointed me at a few sites to do this, but I haven't had a chance to work through the process. I hope to sort it out this weekend. If I do, I'll report back.

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sun Mar 04, 2018 2:29 pm

Replying to myself (again). (I've been busy on other things, so when my researches came to nothing, I put this on the back-burner.) I did sort out the cross-talk, by using audio transformers to isolate the two inputs (ie, Audio O/P Jack and USB Adaptor) but the hum is still present. I now have 3 weeks to fix this, so I've gone back to the old idea of having two USB adaptors and forcing their Card Numbers to be consistent.

The most promising approach seems to be that given at https://alsa.opensrc.org/Udev (scroll down to the C++ version of the solution). Having spent lots of time on this, I still cannot make it work. Testing the method on my Kubuntu PC, I find that I get the error in /var/log/syslog:

Code: Select all

NAME="snd/%c{1}" ignored, kernel device nodes cannot be renamed; please fix it in /etc/udev/rules.d/39-usb-alsa.rules:4


The process generating the error is systemd-udevd.

Looking at the Readme on the Alsa site above, I've just noticed that it is now 5 years old. I also note that there are quite a few postings around the web that indicate that udev rules and operation have changed a lot in recent years.

So is the there a way that works with the latest version of udev?

tropho
Posts: 33
Joined: Mon Feb 26, 2018 11:36 pm

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sun Mar 04, 2018 3:10 pm

This GitHub wiki post from March 2017 should allow you to do what you need to do, which is force consistent, user-defined IDs for your USB audio devices:

https://github.com/dh1tw/remoteAudio/wi ... es-(Linux)

I hope that helps, please let us know if this works.

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sun Mar 04, 2018 3:17 pm

Thanks for that. It certainly looks promising and I'll post back here when I've worked my way through it.

That might take a while though...

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Thu Mar 08, 2018 7:36 am

TerryC65 wrote:
Sun Mar 04, 2018 3:17 pm
Thanks for that. It certainly looks promising and I'll post back here when I've worked my way through it.

That might take a while though...
Well. It did take a while, but not because the solution outlined was wrong, but because it solves the wrong problem unfortunately. I found that it works well to provide an identity for the device, so I can tie a bus or Manufacturer's ID to a label, but not to a channel ID (ie hw:x,y).

At first I thought that I could use omxplayer to play my tracks, (or aplay if I converted all the mp3 files to .wav (urrgh)). I got omxplayer to work reliably, but unfortunately it does not support the playing of a Python List containing all the files I want to play (eg a Playlist). It accepts the List, but only plays the first track before exiting, whereas I need the player to loop endlessly round a playlist until I stop it (by killing the mpg321's process).

I have been using mpg321 as follows:

Code: Select all

subprocess.Popen(mpg321 -l -m -a hw:1,0 Playlist)
Where Playlist is the list of files to be played.

I need to do the code this way, because of Python's thread limit which won't allow me to play two tracks simultaneously (the bells and the music) and then use GPIO events to trap signals from physical switches (to stop playing or change the Playlist) and also to use GPIO to activate a couple of solenoids. By using subprocess.Popen in conjunction with mpg321 I can take advantage of OS multitasking instead of using Python control.

Any suggestions of another solution (or a player that supports alsa labels and looping through a playlist)?

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Fri Mar 09, 2018 1:13 pm

TerryC65 wrote:
Thu Mar 08, 2018 7:36 am
Well. It did take a while, but not because the solution outlined was wrong, but because it solves the wrong problem unfortunately. I found that it works well to provide an identity for the device, so I can tie a bus or Manufacturer's ID to a label, but not to a channel ID (ie hw:x,y).
I just spotted something that I'd missed. The .asoundrc file in the Pi's home directory appears to be overwritten by Raspbian every now and then!!

Apparently, this occurs on reboot if the audio card selection is set to 'Auto' in raspi-config, so I've just set it to 'Force HDMI' and it has survived four reboots so far.

More testing needed, but I may be seeing the light at the end of the tunnel (everything crossed).

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Fri Mar 09, 2018 2:32 pm

TerryC65 wrote:
Fri Mar 09, 2018 1:13 pm
More testing needed, but I may be seeing the light at the end of the tunnel (everything crossed).
The light at the end of the tunnel just got smaller. The two USB Audio
devices now seem to come up consistently on channels hw:0,0 and hw:0,1, but I
now get the error:

Code: Select all

can't open libao driver with device hw:0,0 (is device in use?)
when the bells are required. This is what happens:

At bootup, the program starts playing music to the device labelled CHANCEL
using channel hw:0,1. This works every time. After 15 minutes or less, the
program tries to send the chimes to the device labelled TOWER using channel
hw:0,0. That's when the error occurs.

I assume that this is because only one instance of the driver for the USB
Audio devices is loaded at boot-up and that is in use because it is still
playing the music.

Assuming that I'm right, how do I force the OS to load a second driver
instance for the TOWER?

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Fri Mar 09, 2018 3:08 pm

TerryC65 wrote:
Fri Mar 09, 2018 2:32 pm
The light at the end of the tunnel just got smaller. The two USB Audio
devices now seem to come up consistently on channels hw:0,0 and hw:0,1, but
The light at the end of the tunnel is rapidly vanishing. Having worked consistently for many reboots, I just got a couple of occasions when Card 0
came up as the bcm audio and the TOWER device got moved to Card 2.

So I seem to be back to square one, even when it works, I haven't got a driver and then it doesn't always work anyway....

tropho
Posts: 33
Joined: Mon Feb 26, 2018 11:36 pm

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Fri Mar 09, 2018 10:52 pm

There is something you might have missed from my last post, which was that you also need to modify the .asoundrc file to force particular cards to have particular device ID/channel names, such as hw:0,0 or hw:0,1. The .asoundrc can be used to configure multichannel audio cards, such as those with 7.1 channels or even combine the channels of two or more sound devices into an aliased (fake) device that appears to have the sum of the two sound devices (inputs or outputs from one stereo USB sound device+second stereo USB sound device=one four-channel device).

In your case, you just need to modify your .asoundrc file to make your USB sound devices behave as you need them to. The link to the ALSA Project's .asoundrc guide is here: https://www.alsa-project.org/main/index.php/Asoundrc

tropho
Posts: 33
Joined: Mon Feb 26, 2018 11:36 pm

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Fri Mar 09, 2018 11:00 pm

I forgot to mention that if you have two different sound devices, you should be seeing hw:0,0 and hw:1,0, not hw:0,0 and hw:0,1. The first number after the colon is the card (or USB device in your case) and the second colon is the device on the card (line output). If you are trying to send audio to devices hw:0,0 and hw:0,1 it is failing because it is indeed the same physical device. I imagine you want to send audio to each of your USB sound devices independently, which would be hw:0,x and hw:1,x, with x being whatever the desired output is.

Btw, the .asoundrc file is a hidden file in your home folder (~/.asoundrc). Just cd ~ then nano .asoundrc and you're in business.

I hope that helps!

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Mar 10, 2018 11:20 am

tropho wrote:
Fri Mar 09, 2018 10:52 pm
There is something you might have missed from my last post, which was that you also need to modify the .asoundrc file to force particular cards to have particular device ID/channel names, such as hw:0,0 or hw:0,1.

...

In your case, you just need to modify your .asoundrc file to make your USB sound devices behave as you need them to. The link to the ALSA Project's .asoundrc guide is here: https://www.alsa-project.org/main/index.php/Asoundrc
tropho,
I did modify my .asoundrc file as follows:

Code: Select all

pcm.!default {
	type hw
	card 0
    	device 0
}

ctl.!default {
	type hw
	card 0
    	device 0
}

pcm.TOWER {
    type hw
    card 0
        device 0
}

ctl.TOWER {
    type hw
    card 0
        device 0
}

pcm.CHANCEL {
    type hw
    card 1
        device 0
}

ctl.CHANCEL {
    type hw
    card 1
        device 0
}


However, whatever I did, the hw numbers were inconsistent.

I have now deleted the .asoundrc file and copied the above code into /etc/asound.conf. That seems to consistently (so far) reboot with Card 0 as the bcm card, the TOWER as Card 2 and the CHANCEL as Card 1 (not Cards 0 and 1 as I would have expected). My /etc/udev/rules.d directory contains the file '70-alsa-permanent.rules', which contains:

Code: Select all

SUBSYSTEM!="sound", GOTO="my_usb_audio_end"
ACTION!="add", GOTO="my_usb_audio_end"

ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0808", ATTR{id}="TOWER"
ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="013c", ATTR{id}="CHANCEL"

LABEL="my_usb_audio_end" 

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Mar 10, 2018 11:35 am

tropho wrote:
Fri Mar 09, 2018 11:00 pm
I forgot to mention that if you have two different sound devices, you should be seeing hw:0,0 and hw:1,0, not hw:0,0 and hw:0,1.
Actually that was what I was doing, but I mistyped when I posted here.

Having now decided (see my post above), that the TOWER is hw:2,0 and the CHANCEL is hw:1,0, I have moved forward a bit.

What I am now seeing is somewhat weird. Outside of my Python program I can cd to a Playlist directory and issue:

Code: Select all

mpg321 -m -a hw:1,0 <filename.mp3>
and it works, playing from the USB device designated CHANCEL.

Staying in the same directory I kill playback of the above file and issue:

Code: Select all

mpg321 -m -a hw:2,0 <the same filename.mp3>
and it now plays from the USB device designated TOWER.

If I then kill that playback and move to the directory which contains the bells and issue:

Code: Select all

mpg321 -m -a hw:2,0 <a bells filename.mp3>
The playback fails with the error:

Code: Select all

can't open libao driver with device hw:0,0 (is device in use?)
as mentioned above. If I run top a Zombie mpg321 process shows up.

Any ideas as to what is going on?

tropho
Posts: 33
Joined: Mon Feb 26, 2018 11:36 pm

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Mar 10, 2018 1:22 pm

I think there is a permission issue preventing access to the device, though I'm not sure why it would work once then stop working.

To confirm it works with root privileges, try using sudo before each command or run your script as root (sudo before the python script) and see if that works. If it does work using root/sudo, you can take the somewhat drastic measure of simply making the audio devices folder readable/writable to anyone using chmod o+rw /dev/snd/*

I'm sure someone will reply that simply adding yourself to the audio group should fix this without opening the /snd folder up to the world, but my research suggests it won't solve this problem. It is a risk but a very small one and if your Pi isn't internet facing, the risk is minimal.

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Mar 10, 2018 2:43 pm

tropho wrote:
Sat Mar 10, 2018 1:22 pm
I think there is a permission issue preventing access to the device, though I'm not sure why it would work once then stop working.

To confirm it works with root privileges, try using sudo before each command or run your script as root (sudo before the python script) and see if that works. If it does work using root/sudo, you can take the somewhat drastic measure of simply making the audio devices folder readable/writable to anyone using chmod o+rw /dev/snd/*
Unfortunately that didn't work.

I'm now wondering if there is something inherent in the format of the bells files that is different to the format of the music files. They came from different sources and the bells were recorded by the bellringers in the church. I then converted them using KWave on Kubuntu, so I could have chosen some parameters that the driver doesn't like perhaps.

I have just realised why mpg321 wouldn't work with labels; it does, but I needed to include the device number. So:

Code: Select all

mpg321 -m -a hw:TOWER,0 <filename.mp3
works, but:

Code: Select all

mpg321 -m -a hw:TOWER <filename.mp3
doesn't.

It's obvious really, but not to me.

User avatar
TerryC65
Posts: 78
Joined: Sat May 09, 2015 7:50 am
Location: Wimborne, Dorset, UK

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Sat Mar 10, 2018 4:25 pm

TerryC65 wrote:
Sat Mar 10, 2018 2:43 pm
I'm now wondering if there is something inherent in the format of the bells files that is different to the format of the music files. They came from different sources and the bells were recorded by the bellringers in the church. I then converted them using KWave on Kubuntu, so I could have chosen some parameters that the driver doesn't like perhaps.
OK. I can't quite see why my bells files won't work with mpg321 and the USB Audio devices, but I just realised that it doesn't actually matter because I don't need to loop the bells files inside a list; I only play them one at a time.

So in summary:
  • I play the music using a Python List and the -l attribute of mpg321.
  • I can select the correct USB Audio Device using the contents of the files /etc/udev/rules.d/70-alsa-permanent.rules and asound. conf given above.
Thanks for your help.

tropho
Posts: 33
Joined: Mon Feb 26, 2018 11:36 pm

Re: Identify Audio Channels (hw:x,y) for two USB Audio Adaptors

Tue Mar 13, 2018 12:09 am

No problem! Luckily it was a problem I actually had some experience dealing with in the past :)

Return to “Graphics, sound and multimedia”

Who is online

Users browsing this forum: No registered users and 4 guests