1. 程式人生 > >linux——alsa中多個音效卡裝置時開啟某一指定音效卡的PCM裝置

linux——alsa中多個音效卡裝置時開啟某一指定音效卡的PCM裝置

前言

  最近除錯板子上的3個ADAU1761音訊介面,使用pocketsphinx語音庫呼叫alsa庫的API介面開啟指定的Mic進行錄入語音時出現異常,預設情況只能開啟第一個ADAU1761音訊介面,想開啟第二個或第三個ADAU1761音訊介面時卻出現錯誤,本文記錄一下除錯的過程。

PCM裝置選擇

  移植alsa lib 和alsa utils庫後(移植教程見:傳送門)可使用以下指令檢視音效卡裝置和PCM裝置,具體如下:

[email protected]_project:/# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0
: ADAU1761 [ZED ADAU1761], device 0: 43c00000.axi-i2s-adau-hifi adau-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: ADAU1761_1 [ZED ADAU1761], device 0: 43c10000.axi-i2s-adau-hifi adau-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: ADAU1761_2 [ZED ADAU1761], device 0: 43c20000.axi-i2s-adau-hifi adau-hifi-0
[] Subdevices: 1/1 Subdevice #0: subdevice #0 [email protected]_project:/# arecord -l **** List of CAPTURE Hardware Devices **** card 0: ADAU1761 [ZED ADAU1761], device 0: 43c00000.axi-i2s-adau-hifi adau-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: ADAU1761_1 [ZED ADAU1761], device 0: 43
c10000.axi-i2s-adau-hifi adau-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 2: ADAU1761_2 [ZED ADAU1761], device 0: 43c20000.axi-i2s-adau-hifi adau-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 [email protected]_project:/# ls -l /dev/snd crw-rw---- 1 root root 116, 0 Jan 1 00:00 controlC0 crw-rw---- 1 root root 116, 32 Jan 1 00:00 controlC1 crw-rw---- 1 root root 116, 64 Jan 1 00:00 controlC2 crw-rw---- 1 root root 116, 24 Jan 1 00:00 pcmC0D0c crw-rw---- 1 root root 116, 16 Jan 1 00:00 pcmC0D0p crw-rw---- 1 root root 116, 56 Jan 1 00:00 pcmC1D0c crw-rw---- 1 root root 116, 48 Jan 1 00:00 pcmC1D0p crw-rw---- 1 root root 116, 88 Jan 1 00:00 pcmC2D0c crw-rw---- 1 root root 116, 80 Jan 1 00:00 pcmC2D0p crw-rw---- 1 root root 116, 33 Jan 1 00:00 timer

如上,共有三個音效卡裝置:
card 0: ADAU1761
card 1: ADAU1761_1
card 2: ADAU1761_2
在使用aplay和arecord指令進行播放和錄音時可正常選擇其中某一個音效卡,如:

//使用ADAU1761_1錄音
[email protected]_project:/# arecord -D hw:ADAU1761_1 -fS32_LE -d10 -c2 -r48000 s32_                    
le.wav                                                                                              
Recording WAVE 's32_le.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Stereo

//使用ADAU1761播放
[email protected]_project:/# aplay -D hw:ADAU1761 -fS32_LE -c2 -r48000 s32_le.wav                       
Playing WAVE 's32_le.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Stereo

  移植完pocketsphinx庫後(見教程:傳送門),呼叫pocketsphinx_continuous指令開啟MIC進行語音識別,預設可開啟ADAU1761裝置,而開啟其他兩個音效卡出現異常,報錯:
Failed to set PCM device to 16-bit signed PCM: Invalid argument
FATAL_ERROR: “continuous.c”, line 246: Failed to open audio device
這裡寫圖片描述
檢視pocketsphinx-0.8\src\programs\continuous.c 中原始碼,為ad_open_dev() API介面開啟裝置失敗。

/*
 * Main utterance processing loop:
 *     for (;;) {
 *     wait for start of next utterance;
 *     decode utterance until silence of at least 1 sec observed;
 *     print utterance result;
 *     }
 */
static void
recognize_from_microphone()
{
    ad_rec_t *ad;
    int16 adbuf[4096];
    int32 k, ts, rem;
    char const *hyp;
    char const *uttid;
    cont_ad_t *cont;
    char word[256];

    if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),
                          (int)cmd_ln_float32_r(config, "-samprate"))) == NULL)
        E_FATAL("Failed to open audio device\n");


    //。。。。。。。省略

}

接著檢視ad_open_dev函式(\sphinxbase-0.8\src\libsphinxad\ad_alsa.c檔案中),裡面呼叫snd_pcm_open函式開啟PCM裝置,若輸入的dev是NULL,則使用DEFAULT_DEVICE裝置。

ad_rec_t *
ad_open_dev(const char *dev, int32 sps)
{
    ad_rec_t *handle;
    snd_pcm_t *dspH;

    int err;

    if (dev == NULL)
        dev = DEFAULT_DEVICE;

    err = snd_pcm_open(&dspH, dev, SND_PCM_STREAM_CAPTURE, 0);
    if (err < 0) {
        fprintf(stderr,
                "Error opening audio device %s for capture: %s\n",
                dev, snd_strerror(err));
        return NULL;
    }

    if (setparams(sps, dspH) < 0) {
        return NULL;
    }
    if (setlevels(dev) < 0) {
        return NULL;
    }
    if ((handle = (ad_rec_t *) calloc(1, sizeof(ad_rec_t))) == NULL) {
        fprintf(stderr, "calloc(%d) failed\n", (int)sizeof(ad_rec_t));
        abort();
    }

    handle->dspH = dspH;
    handle->recording = 0;
    handle->sps = sps;
    handle->bps = sizeof(int16);

    return (handle);
}

DEFAULT_DEVICE的定義:

#define DEFAULT_DEVICE "default"

snd_pcm_open函式的使用介紹見:傳送門,檢視庫的使用介紹,name引數的使用例程,裝置名稱格式分別使用hw:0,0plughw:0,0
這裡寫圖片描述
這裡寫圖片描述
預設情況下開啟的裝置是card 0,預設情況下載入/usr/local/alsa/alsa.conf檔案,該檔案中有預設開啟的音效卡引數:

# defaults
#

# show all name hints also for definitions without hint {} section
defaults.namehint.showall off
# show just basic name hints
defaults.namehint.basic on
# show extended name hints
defaults.namehint.extended off
#
defaults.ctl.card 0 //預設音效卡0
defaults.pcm.card 0 //預設音效卡0
defaults.pcm.device 0 //預設裝置0
defaults.pcm.subdevice -1
defaults.pcm.nonblock 1
defaults.pcm.compat 0
defaults.pcm.minperiodtime 5000         # in us
defaults.pcm.ipc_key 5678293
defaults.pcm.ipc_gid audio
defaults.pcm.ipc_perm 0660
defaults.pcm.dmix.max_periods 0
defaults.pcm.dmix.rate 48000
defaults.pcm.dmix.format "unchanged"
defaults.pcm.dmix.card defaults.pcm.card
defaults.pcm.dmix.device defaults.pcm.device
defaults.pcm.dsnoop.card defaults.pcm.card
defaults.pcm.dsnoop.device defaults.pcm.device
defaults.pcm.front.card defaults.pcm.card
defaults.pcm.front.device defaults.pcm.device
defaults.pcm.rear.card defaults.pcm.card
defaults.pcm.rear.device defaults.pcm.device
defaults.pcm.center_lfe.card defaults.pcm.card
defaults.pcm.center_lfe.device defaults.pcm.device
defaults.pcm.side.card defaults.pcm.card
defaults.pcm.side.device defaults.pcm.device
defaults.pcm.surround21.card defaults.pcm.card
defaults.pcm.surround21.device defaults.pcm.device
defaults.pcm.surround40.card defaults.pcm.card
defaults.pcm.surround40.device defaults.pcm.device
defaults.pcm.surround41.card defaults.pcm.card
defaults.pcm.surround41.device defaults.pcm.device
defaults.pcm.surround50.card defaults.pcm.card
defaults.pcm.surround50.device defaults.pcm.device
defaults.pcm.surround51.card defaults.pcm.card
defaults.pcm.surround51.device defaults.pcm.device
defaults.pcm.surround71.card defaults.pcm.card
defaults.pcm.surround71.device defaults.pcm.device
defaults.pcm.iec958.card defaults.pcm.card
defaults.pcm.iec958.device defaults.pcm.device
defaults.pcm.modem.card defaults.pcm.card
defaults.pcm.modem.device defaults.pcm.device
# truncate files via file or tee PCM
defaults.pcm.file_format        "raw"
defaults.pcm.file_truncate      true
defaults.rawmidi.card 0
defaults.rawmidi.device 0
defaults.rawmidi.subdevice -1
defaults.hwdep.card 0
defaults.hwdep.device 0
defaults.timer.class 2
defaults.timer.sclass 0
defaults.timer.card 0
defaults.timer.device 0
defaults.timer.subdevice 0                                                

  若要開啟對應的音效卡,修改上述引數即可實現載入對應的音效卡裝置。
  檢視ALSA庫的引數資料,其API使用的是邏輯裝置名,如下:
  API庫使用邏輯裝置名而不是裝置檔案。裝置名字可以是真實的硬體名字也可以是外掛名字。硬體名字使用hw:i,j這樣的格式。其中i是卡號,j是這塊音效卡上的裝置號。第一個聲音裝置是hw:0 , 0.這個別名預設引用第一塊聲音裝置並且在本文示例中一真會被用到。外掛使用另外的唯一名字,比如 plughw:0 , 0:,表示一個外掛,這個外掛不提供對硬體裝置的訪問,而是提供像取樣率轉換這樣的軟體特性,硬體本身並不支援這樣的特性。
ALSA庫的資料見:傳送門,邏輯裝置名的使用例程見:
這裡寫圖片描述這裡寫圖片描述
使用* -adcdev plughw:1,0*引數開啟對應音效卡,如下開啟音效卡1:

pocketsphinx_continuous -adcdev plughw:1,0 -hmm tdt_sc_8k/ -lm 6690.lm -dict 6690.dic

成功開啟音效卡1,連線MIC說話,語音識別結果如下:
這裡寫圖片描述
使用hw:0 , 0引數開啟對應音效卡,彈出無效引數的錯誤:

pocketsphinx_continuous -adcdev hw:1,0 -hmm tdt_sc_8k/ -lm 6690.lm -dict 6690.dic

這裡寫圖片描述
對比alsa.conf檔案中hw和plughw中引數結構如下,具體使用-adcdev hw:1,0開啟音效卡失敗的原因還未查到。
這裡寫圖片描述

總結

  使用pocketsphinx語音庫呼叫alsa庫的API介面開啟指定的音效卡裝置主要以下兩種方法:
(1)修改alsa.conf檔案中的預設音效卡引數;(不推薦)
(2)使用* -adcdev plughw:n,0*引數開啟對應的音效卡n,例如:

pocketsphinx_continuous -adcdev plughw:1,0 -hmm tdt_sc_8k/ -lm 6690.lm -dict 6690.dic

相關推薦

linux——alsa音效裝置開啟指定音效PCM裝置

前言   最近除錯板子上的3個ADAU1761音訊介面,使用pocketsphinx語音庫呼叫alsa庫的API介面開啟指定的Mic進行錄入語音時出現異常,預設情況只能開啟第一個ADAU1761音訊介面,想開啟第二個或第三個ADAU1761音訊介面時卻出現錯誤

ios-day18-09(使用CAKeyframeAnimation實現對UIView在位置之間平移、沿著條路徑平移)

// // JLViewController.m // 09-核心動畫 // // Created by XinYou on 15-4-2. // Copyright (c) 2015年 vxinyou. All rights reserved. // #import "JLViewControll

linux ln -s 實現tomcat 專案檔案共享

專案A   需要訪問專案B 的檔案, 可以通過 ln-s 命令 將 A 路徑連結到專案B 的路徑下。 [[email protected] insurance-mall]# service tomcat8 start^C [[email protecte

linux ln -s 實現tomcat 專案檔案共享

專案A   需要訪問專案B 的檔案, 可以通過 ln-s 命令 將 A 路徑連結到專案B 的路徑下。 [[email protected] insurance-mall]# service tomcat8 start^C [[email protected] ins

0066 LinuxJava檔案打包成單個可執行jar檔案及其manifest.mf檔案編寫規則

現在我有三個Java類檔案:GuessGame.java Player.java GameLauncher.java(含主函式) 先用編譯命令: javac GuessGame.java Player

linux 驅動建立裝置

linux 驅動中建立一個裝置的例子很多,以下例子是建立多個字元裝置的例子,包括驅動部分和測試部分 驅動部分包括 globalmem.c  Makefile兩個檔案: globalmem.c file: #include <linux/module.h>

linux驅動支援裝置

1.註冊裝置 insmod driverName.ko //主要是呼叫xxx_init()函式向chrdev中註冊裝置號(代表一類裝置),和將要使用的裝置數量 // xxx_init()中利用函式結構體,file_operations初始化cdev,然後把cdev和註冊的

Linux下nginx+Tomcat負載均衡的實現

java 負載 均衡 bootstra 火墻 瀏覽器 startup 顯示 tomcat的配置 由於項目需要,共創建了10個Tomcat端,由nginx負責轉發。9個Tomcat端口分別是8080,11000,12000,13000,14000,15000,16000,17

Linux下SVN+Tomcat自動部署

mod .html 部署 update語句 hooks 參考 eba bsp auth 項目中都是jsp開發,所以用到Tomcat。 在我文章中也寫過多個Tomcat 的部署,具體可以參考:http://www.cnblogs.com/magmell/p/7045193.h

js 刪除數組元素

true arr return contain index var nbsp log dex js中如果使用forEach的話 , splice刪除的時候會導致js的數組的length發生改變 , 因此會出現本應該刪除的元素沒有被刪除 . 因此 , 我的想法是 : 使用i

如何將Linux系統的目錄及文件備份並壓縮到一個文件,以方面保持和傳遞?

如何將linux系統的多個目錄及文件備份並壓縮到一個文件 以方面保持和傳遞? 1.備份Linux系統  window系統在運行狀態下,我們是無法將文件拷貝出來的,那麽在Linux下呢?她的文件結構式一種樹型結構。而且在系統運行的時候我們可以進行打包所有系統文件。特別要說的在Linux的root賬戶具備

Switch Case語句值匹配同一個代碼塊的寫法

har com arch mssql pre html www ase cas switch ($p) { case ‘home‘: case ‘‘: $current_home = ‘current‘; break

spring+activemqconsumer同時處理消息遇到的性能問題

每次 分發 active 行數據 裏的 數據 情況 實現 出隊 最近在做數據對接的工作,用到了activemq,我需要從activemq中接收消息並處理,但是我處理數據的步驟稍微復雜,漸漸的消息隊列中堆的數據越來越多,就想到了我這邊多開幾個線程來處理消息。 可是會發現,服務

使用github作為maven倉庫存放發布自己的jar包依賴 實現項目公共部分代碼的集中,避免團隊項目之間代碼的復制粘貼

地址 oba post 直接 bubuko http tps hub 之間 使用github作為maven倉庫存放發布自己的jar包依賴 實現多個項目公共部分代碼的集中,避免團隊中多個項目之間代碼的復制粘貼。 1、首先在本地maven位置的配置文件setting.xml(沒

Python刪除list相同元素

個人 err val pos 倒序 pan move 信息 style pop和remove方法都可以刪除list中的元素,個人更傾向於使用remove方法,因為在刪除過程中不會打印信息,安靜的把任務完成。 pop方法:刪除過程中會打印信息 >>>

【K8S學習筆記】Part3:同一Pod容器間使用共享卷進行通信

ash source net def exe tput stat policy container 本文將展示如何使用共享卷(Volume)來實現相同Pod中的兩個容器間通信。 註意:本文針對K8S的版本號為v1.9,其他版本可能會有少許不同。 0x00 準備工作 需要有一

form表單button按鈕必須聲明type類型

orm 管理系 多個 分享 com 圖片 log bmi 一個 最近在做一個後臺管理系統,發現了一個小bug: 問題描述:form表單中有多個button按鈕(以下圖為例),如果第一個button不寫type屬性,那麽點擊第一個button按鈕會觸發submit事件; 解決

unity門的開關動畫保持獨立性

eno date cast ray nsf color input plan wak List<Animation> storeAnimation; public void Awake() { storeAnimation = new Li

Dotnet Core Cli 解決方案項目的相互引用和第三方庫引用

pac todo core 多個項目 json ren .json 三方庫 方案 dotnet add app/app.csproj reference lib/lib.csproj app項目引用lib項目 dotnet add package Newtonsoft.

linux nginx配置網站

vhost host 編輯 dir OS nginx 文件夾 CA nginx配置 1.把網站配置在hom目錄下,需要建立wwwroot目錄 1.在nginx.conf 增加inlcude代碼,然後創建一個vhost,最後配置個xxx.com.conf //編輯n