天天看點

PYNQ開發闆上使用USB聲霸卡+OSS相容層播放音頻

PYNQ開發闆上使用USB聲霸卡+OSS相容層播放音頻需要經過聯網裝庫,編譯驅動子產品,運作三個步驟。

聯網裝庫

首先需要将PYNQ開發闆連上網,才能安裝所需的庫。方法是在電腦上設定共享網絡,但要注意大部分作業系統在共享網絡的時候無法自己指定本機IP,是以需要修改PYNQ開發闆的IP來适應電腦自動設定的IP。設定共享網絡的方法網上教程有很多,這裡不再贅述。

設定完共享網絡後,注意不要關閉開發闆,因為電腦的IP已經改了,如果重新開機開發闆網關不對SSH就連不上了。這時需要檢視電腦的ip(注意是有線區域網路下的ip),Windows下使用

ipconfig

,Linux下使用

ifconfig

。如我的Ubuntu在有線區域網路下的ip是10.42.0.1,由于網關是255.255.255.0,是以PYNQ開發闆的IP必須設定為10.42.0.*。在我的環境下,設定IP的方法是編輯

/etc/network/interfaces.d/eth0

,然後将其中的address這一行的IP位址修改為10.42.0.2。

然後禁用再啟用一下電腦的有線網功能并重新開機開發闆,嘗試能否連進去,連進去以後再嘗試ping外網,都可以才算成功。接下來就可以裝庫了,執行:

sudo apt update
sudo apt install alsa-base alsa-utils alsa-oss bc
           

編譯驅動子產品

下載下傳核心源代碼,我PYNQ上的Linux核心版本為5.4.0,可以在xilinx的linux核心倉庫下載下傳,其他版本的核心源碼也可以在該倉庫的其他分支下載下傳。

下載下傳并傳到開發闆上後,執行:

unzip linux-xlnx-xlnx_rebase_v5.4_2020.1.zip
           

解壓結束後進入該檔案夾,然後需要将目前系統的核心配置檔案複制過來,執行:

sudo cp /lib/modules/$(uname -r)/build/.config .
           

配置需要編譯的驅動子產品,執行:

make menuconfig
           

進入

Device Drivers

->

Sound card support

Advanced Linux Sound Architecture

USB sound devices

,光标移至

USB Audio/MIDI driver

,按M鍵選擇編譯此子產品,儲存然後一直按Esc鍵退出。執行以下指令:

make prepare
make -C . M=sound
           

編譯驅動子產品,生成擴充名為ko的子產品檔案,将它們複制到核心檔案夾中:

sudo mkdir -p /lib/modules/$(uname -r)/kernel/sound/core
sudo mkdir -p /lib/modules/$(uname -r)/kernel/sound/usb
sudo cp sound/core/*.ko /lib/modules/$(uname -r)/kernel/sound/core
sudo cp sound/usb/*.ko /lib/modules/$(uname -r)/kernel/sound/usb
           

然後安裝這些子產品:

sudo depmod
           

之後插上USB聲霸卡,驅動子產品應該會自動加載,可以用指令

lsmod

檢視子產品是否被成功加載,在我的系統上被加載的有以下4個子產品:

Module                  Size  Used by
snd_usb_audio         167936  0
snd_hwdep              16384  1 snd_usb_audio
snd_usbmidi_lib        24576  1 snd_usb_audio
snd_rawmidi            24576  1 snd_usbmidi_lib
           

如果沒有自動加載,可以手動加載:

sudo modprobe snd-usb-audio
           

此時可以檢視聲霸卡是否已被識别:

sudo aplay -l
           

如果輸出中出現card 1,則需要配置一下聲霸卡編号,因為alsa音頻庫預設使用的聲霸卡是0号聲霸卡,而USB聲霸卡被配置設定的編号是1,是以需要修改alsa的配置檔案,路徑為

/usr/share/alsa/alsa.conf

,在裡面找到

defaults.pcm.card 0

這一行,把0改成1。

這時候應該可以播放音樂了:

sudo aplay test.wav
           

運作

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
int main() {    
    // 打開裝置檔案
    int fd = open("/dev/dsp", O_RDWR);
    if (fd < 0) {
        perror("open error\n"); return 1;
    }

    // test.wav為16位,雙聲道,采樣率為20000的波形檔案
    int bit = 16, rate = 20000, channel = 2;

    ioctl(fd, SOUND_PCM_WRITE_BITS, &bit);
    ioctl(fd, SOUND_PCM_WRITE_RATE, &rate);
    ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &channel);

    /*打開音樂檔案*/
    int fp = open("test.wav", O_RDONLY);
    if(fp < 0){
        perror("open fp error!\n"); return 1;
    }

    /*求檔案的大小*/
    //這裡直接給出了,要計算可以用fstat函數或fseek+ftell函數
    int len = 800180;

    char *buf = (char *)malloc(len);
    memset(buf, 0, len);

    // 讀檔案到buf中
    int rd = read(fp, buf, len);
    if(rd < 0){
        perror("read wav error!\n"); return 1;
    }
    close(fp);

    // 把buf寫到裝置檔案中
    int wr = write(fd, buf, len);
    if(wr < 0){
        perror("write dsp error!\n"); return 1;
    }

    free(buf); buf = NULL;
    return 0;
}
           
sudo LD_PRELOAD=libaoss.so ./audio
           

繼續閱讀