当前位置:   article > 正文

【在Linux下如何同时使用多个音频输出设备播放不同的音频】_外接声卡 lunix

外接声卡 lunix

干货!干货!干货!在Linux下如何同时使用多个音频输出设备播放不同的音频


前言

最近在开发一个车辆系统音频播报的系统,项目的需求是需要选择多个声卡设备来进行播放不同的音频,在网上查了许多资料,历经大半个月终于搞定了,放出来给大家免费参考参考,【主要是看到某些博主居然要收费,心里不爽,话不多,直接上源码】。


声卡绑定配置

步骤一
本功能包基于的声卡是绿联:https://detail.tmall.com/item.htm?abbucket=12&id=559780789362&ns=1&spm=a21n57.1.0.0.748e523c5aANXB
本设备hidraw0、hidraw1为两个外接的USB声卡
查看声卡是否接入
lsusb
Bus 001 Device 003: ID 0c76:1676 JMTek, LLC. USB PnP Audio Device
Bus 001 Device 002: ID 0c76:1676 JMTek, LLC. USB PnP Audio Device
***
***
***
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
出现的两个外置USB声卡串口号是一样的,是因为厂家采用的串口芯片是一样的;所以不能用串口号来区分两张声卡,接下来我们采用的是利用端口号加路径的方式来区分并绑定设备。
ls /dev/*
hidraw0 hidraw1 hidraw3 hidraw4
  • 1
  • 2
查看串口以及端口信息,测试了发现没有USB串口独立的特征信息,所以无法从串口信息来识别, 唯一一个不变的3-3:1.0, 而这个实际上是代表电脑上这个USB口编号,也就是说只是连在这个USB端口上的串口都叫这个ID.
udevadm info /dev/hidraw*

P: /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/0003:0C76:1676.0001/hidraw/hidraw0
N: hidraw0
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/0003:0C76:1676.0001/hidraw/hidraw0
E: DEVNAME=/dev/hidraw0
E: MAJOR=239
E: MINOR=0
E: SUBSYSTEM=hidraw

P: /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/0003:0C76:1676.0002/hidraw/hidraw1
N: hidraw1
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/0003:0C76:1676.0002/hidraw/hidraw1
E: DEVNAME=/dev/hidraw1
E: MAJOR=239
E: MINOR=1
E: SUBSYSTEM=hidraw
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
查看声卡所接的USB端口对应的端口号方法
ll /sys/class/hidraw/hidraw*

lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw0 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/0003:0C76:1676.0001/hidraw/hidraw0/
lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw1 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/0003:0C76:1676.0002/hidraw/hidraw1/
lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw2 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.2/0003:046D:C52B.0005/hidraw/hidraw2/
lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw3 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.2/0003:046D:C52B.0005/0003:046D:404D.0006/hidraw/hidraw3/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
绑定【USB端口号】KERNELS硬件端口号绑定
sudo gedit /etc/udev/rules.d/com_port.rules
  • 1
根据自身情况,修改rules文件。
KERNELS表示硬件的USB接口名,不同编号,表示不同的usb接口.
其中,第一条代表连接到USB端口号为1-3:1.3的声卡对应的软链接文件为Speaker/Interior;第二条代表连接到USB端口号为1-4:1.3的声卡对应的软链接文件为Speaker/Exterior;然后保存并重启电脑。
SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", KERNELS=="1-3:1.3", MODE="0666", SYMLINK+="Interior_Speaker", OWNER="pixkit3", GROUP="root"
SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", KERNELS=="1-4:1.3", MODE="0666", SYMLINK+="Exterior_Speaker", OWNER="pixkit3", GROUP="root"
  • 1
  • 2
运行以下命令使修改立即生效
sudo udevadm trigger
  • 1
查看是否软连接成功,运行以下命令查看USB设备名更改情况:
ls -l /dev |grep hidraw*

lrwxrwxrwx   1 root    root           7  9月 11 11:15 Exterior_Speaker -> hidraw1
crw-rw-rw-   1 kit3 kit3 239,   0  9月 11 11:15 hidraw0
crw-rw-rw-   1 kit3 kit3 239,   1  9月 11 11:15 hidraw1
crw-------   1 root    root    239,   2  9月 11 11:15 hidraw2
crw-------   1 root    root    239,   3  9月 11 11:15 hidraw3
lrwxrwxrwx   1 root    root           7  9月 11 11:15 Interior_Speaker -> hidraw0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
如输出以上信息,表示已经软连接成功。
通过以上步骤,就把hidraw0取别名为Interior_Speaker,把hidraw1取别名为Exterior_Speaker,以后在程序里直接访问Interior_Speaker\Exterior_Speaker,就可以与这两个设备通信了。
特注意:只要是插到这个USB端口的串口都会被改为指定名,所以该方法只能将设备插入在指定的USB端口上。
步骤二
配置alsad的asound.conf文件,如果没有则自行新建一个asound.conf文件,把Interior_Speaker、Exterior_Speaker 映射到声卡0、声卡1上,具体在那个需要 aplay -l查看。
sudo gedit /etc/asound.conf

pcm.Interior_Speaker {
    type hw
    card 0
}

ctl.Interior_Speaker {
    type hw
    card 0
}


pcm.Exterior_Speaker {
    type hw
    card 1
}

ctl.Exterior_Speaker {
    type hw
    card 1
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
保存配置文件即可
查看系统声卡索引号
在输出的内容里面就有我们插入的两张声卡。
aplay -l or aplay -L

**** List of PLAYBACK Hardware Devices ****
card 0: Device_1 [USB PnP Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Device [USB PnP Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: PCH [HDA Intel PCH], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
安装 pavucontrol
sudo apt-get install pavucontrol   # Debian/Ubuntu系统

按照下图所示进行设置
  • 1
  • 2
  • 3

声卡绑定配置

步骤一

本功能包基于的声卡是绿联:https://detail.tmall.com/item.htm?abbucket=12&id=559780789362&ns=1&spm=a21n57.1.0.0.748e523c5aANXB

本设备hidraw0、hidraw1为两个外接的USB声卡

查看声卡是否接入
lsusb
Bus 001 Device 003: ID 0c76:1676 JMTek, LLC. USB PnP Audio Device
Bus 001 Device 002: ID 0c76:1676 JMTek, LLC. USB PnP Audio Device
***
***
***
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
出现的两个外置USB声卡串口号是一样的,是因为厂家采用的串口芯片是一样的;所以不能用串口号来区分两张声卡,接下来我们采用的是利用端口号加路径的方式来区分并绑定设备。
ls /dev/*
hidraw0 hidraw1 hidraw3 hidraw4
  • 1
  • 2
查看串口以及端口信息,测试了发现没有USB串口独立的特征信息,所以无法从串口信息来识别, 唯一一个不变的3-3:1.0, 而这个实际上是代表电脑上这个USB口编号,也就是说只是连在这个USB端口上的串口都叫这个ID.
udevadm info /dev/hidraw*

P: /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/0003:0C76:1676.0001/hidraw/hidraw0
N: hidraw0
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/0003:0C76:1676.0001/hidraw/hidraw0
E: DEVNAME=/dev/hidraw0
E: MAJOR=239
E: MINOR=0
E: SUBSYSTEM=hidraw

P: /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/0003:0C76:1676.0002/hidraw/hidraw1
N: hidraw1
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/0003:0C76:1676.0002/hidraw/hidraw1
E: DEVNAME=/dev/hidraw1
E: MAJOR=239
E: MINOR=1
E: SUBSYSTEM=hidraw
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

查看声卡所接的USB端口对应的端口号方法

ll /sys/class/hidraw/hidraw*

lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw0 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/0003:0C76:1676.0001/hidraw/hidraw0/
lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw1 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.3/0003:0C76:1676.0002/hidraw/hidraw1/
lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw2 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.2/0003:046D:C52B.0005/hidraw/hidraw2/
lrwxrwxrwx 1 root root 0  9月 11 09:33 /sys/class/hidraw/hidraw3 -> ../../devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7:1.2/0003:046D:C52B.0005/0003:046D:404D.0006/hidraw/hidraw3/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

绑定【USB端口号】KERNELS硬件端口号绑定

sudo gedit /etc/udev/rules.d/com_port.rules
  • 1
根据自身情况,修改rules文件。
KERNELS表示硬件的USB接口名,不同编号,表示不同的usb接口.
其中,第一条代表连接到USB端口号为1-3:1.3的声卡对应的软链接文件为Speaker/Interior;第二条代表连接到USB端口号为1-4:1.3的声卡对应的软链接文件为Speaker/Exterior;然后保存并重启电脑。
SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", KERNELS=="1-3:1.3", MODE="0666", SYMLINK+="Interior_Speaker", OWNER="pixkit3", GROUP="root"
SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", KERNELS=="1-4:1.3", MODE="0666", SYMLINK+="Exterior_Speaker", OWNER="pixkit3", GROUP="root"
  • 1
  • 2
运行以下命令使修改立即生效
sudo udevadm trigger
  • 1
查看是否软连接成功,运行以下命令查看USB设备名更改情况:
ls -l /dev |grep hidraw*

lrwxrwxrwx   1 root    root           7  9月 11 11:15 Exterior_Speaker -> hidraw1
crw-rw-rw-   1 pixkit3 pixkit3 239,   0  9月 11 11:15 hidraw0
crw-rw-rw-   1 pixkit3 pixkit3 239,   1  9月 11 11:15 hidraw1
crw-------   1 root    root    239,   2  9月 11 11:15 hidraw2
crw-------   1 root    root    239,   3  9月 11 11:15 hidraw3
lrwxrwxrwx   1 root    root           7  9月 11 11:15 Interior_Speaker -> hidraw0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如输出以上信息,表示已经软连接成功。

通过以上步骤,就把hidraw0取别名为Interior_Speaker,把hidraw1取别名为Exterior_Speaker,以后在程序里直接访问Interior_Speaker\Exterior_Speaker,就可以与这两个设备通信了。

特注意:只要是插到这个USB端口的串口都会被改为指定名,所以该方法只能将设备插入在指定的USB端口上。

步骤二

配置alsad的asound.conf文件,如果没有则自行新建一个asound.conf文件,把Interior_Speaker、Exterior_Speaker 映射到声卡0、声卡1上,具体在那个需要 aplay -l查看。
sudo gedit /etc/asound.conf

pcm.Interior_Speaker {
    type hw
    card 0
}

ctl.Interior_Speaker {
    type hw
    card 0
}


pcm.Exterior_Speaker {
    type hw
    card 1
}

ctl.Exterior_Speaker {
    type hw
    card 1
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
保存配置文件即可,接下来查看系统声卡索引号
在输出的内容里面就有我们插入的两张声卡。
aplay -l or aplay -L
  • 1

card 1: Device [USB PnP Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 2: Audio [iStore Audio], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0

安装 pavucontrol

sudo apt-get install pavucontrol   # Debian/Ubuntu系统
  • 1
按照下图所示进行设置
	特别注意:设备上插入了两个USB声卡,所以下图显示有两个USB声卡设备,在Profile选项里选择输出类型;
	在这里我USB声卡1选择的是Analog Stereo Output 做为音频的输出设备;声卡2选择的是Analog Stereo Duplex,因为声卡2上接了一个麦克风,不使用显卡所带的声卡,可以将HDA Nvidia关掉。
	注意:
	"Analog Stereo Duplex"是 PulseAudio 中的一个音频配置配置文件,用于表示同时支持音频输入(如麦克风)和音频输出(如扬声器或耳机)的声音配置。
	"Analog Stereo Output" 这是标准的模拟立体声输出,通常用于连接到内置或外置扬声器的设备。
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

代码:


import pyaudio
import simpleaudio as sa
import wave

# 获取可用的声音设备列表
def list_audio_devices():
    p = pyaudio.PyAudio()
    info = p.get_host_api_info_by_index(0)
    numdevices = info.get('deviceCount')
    devices = []

    for i in range(0, numdevices):
        device_info = p.get_device_info_by_host_api_device_index(0, i)
        device_name = device_info.get('name')
        devices.append((i, device_name))
        print(f"Device {i}: {device_info['name']}, Supported Sample Rates: {device_info['defaultSampleRate']}, Max Channels: {device_info['maxOutputChannels']}")


    return devices

# 选择特定声卡并播放音频
def play_audio_on_device(audio_file, device_index):
    try:
        # 使用 PyAudio 控制音频输出设备
        p = pyaudio.PyAudio()
        wave_file = wave.open(audio_file, 'rb')

        stream = p.open(output_device_index=device_index,
                        format=p.get_format_from_width(wave_file.getsampwidth()),
                        channels=wave_file.getnchannels(),
                        # rate=wave_file.getframerate(),
                        rate=48000,  # 指定所需的采样率
                        output=True)

        data = wave_file.readframes(1024)

        # 从音频文件中读取数据并通过 PyAudio 输出到所选的声卡
        while data:
            stream.write(data)
            data = wave_file.readframes(1024)

        stream.stop_stream()
        stream.close()
        p.terminate()

    except Exception as e:
        print("播放音频出错:", str(e))

# 获取声卡列表并选择一个声卡(例如,选择第一个声卡)
audio_devices = list_audio_devices()
if len(audio_devices) > 1:
    # 初始化声卡参数
    selected_device_index_out = audio_devices[1][0] #音箱
    selected_device_index_in = audio_devices[0][0] #耳机
    
    # 播放音频文件(例如,'audio.wav')到所选声卡
    audio_file_path_1 = '/home/src/vehicle/external/vehicle_voice_alert_system/src/vehicle_voice_alert_system/resource/sound/running_music.wav'
    audio_file_path_2 = '/home/src/vehicle/external/vehicle_voice_alert_system/src/vehicle_voice_alert_system/resource/sound/stop.wav'
    
    # 选择播放声卡
    play_audio_on_device(audio_file_path_2, selected_device_index_in)
    play_audio_on_device(audio_file_path_1, selected_device_index_out)

    
else:
    print("没有找到可用的声卡")



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

总结

以上就是今天要讲的内容,本文仅仅简单介绍了主题文章使用,本着开源的精神加班熬夜给大伙儿谋福利,还望您动动手指点个赞

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/326024
推荐阅读
相关标签