0 引 言
LabVIEW 是美國NI公司1986年推出的一種圖形化的編程語言和開發環境。作為虛擬儀器開發平臺,由于其圖形化的編程方式具有簡單易學、直觀方便、功能強大等特點,是很多工程設計人員進行虛擬儀器開發的首選。生產者/消費者設計模式是NI公司最新推出的程序設計概念,它從主/從設計模式發展而來,生產者/消費者設計模式將生產和消費數據速度不同的任務分開處理,大大提高了不同速率的多個循環之間數據共享的能力,對于多任務處理和實時性、連續性要求嚴格的程序設計,生產者/消費者設計模式是較好的選擇。在虛擬儀器系統中,硬件解決信號的輸入和輸出,軟件可以方便地更新儀器系統的功能,以適應不同使用者的需要。其中信號的輸入部分一般使用數據采集卡實現,商用的數據采集卡具有較大的逋用性。普通聲卡具有16位的量化精度、數據采集頻率是44 kHz,完全可以滿足特定音頻信號范圍內數據采集的需要,個別性能指標還優于商用數據采集卡,而價格卻為商用數據采集卡的十幾分之一甚至幾十分之一。若保證信號采集的逼真性,在采集過程中的連續性和實時控制顯得尤為重要。
本文以LabVIEW為平臺,著重介紹了生產者/消費者模式的實現,以及在實時控制的連續音頻采集系統中的應用。
1 生產者/消費者設計模式概念及其實現
1.1 生產者/消費者設計模式概念
生產者/消費者設計模式包括多個并行循環,每個循環以不同的速率執行任務。一個循環作為生產數據的循環,其他循環作為消費數據的循環。生產數據的循環控制所有消費數據的循環,并且使用通信技術與它們進行通信。
1.2 生產者循環與消費者循環之間的通信
在LabVIEW程序設計過程中,變量(局部變量和全局變量)、通知器、隊列常用于多個循環之間傳遞數據。
LabVIEW中的變量是程序框圖中的元素,通過它可以在另一位置訪問或存儲數據。根據不同的變量類型,數據的實際位置也不一樣。局部變量將數據存儲在前面板的輸入控件和顯示控件中,全局變量和單進程共享變量將數據存儲在特殊的通過多個VI可以訪問的倉庫中。不管變量將數據存儲在何處,所有的變量都可以在不使用連線連接兩個地方的條件下把數據從一個地方傳遞到另一個地方,而不必使用正常的數據流。但是變量的使用有著其自身的缺點,變量不僅不能保證各個循環之間的同步,而且使用變量會破壞LabVIEW的數據流模式,在對變量進行讀寫操作時容易產生內存拷貝,浪費內存資源,影響系統運行效率。
變量還允許競爭狀態的出現,競爭狀態不容易識別和調試,因為輸出取決于操作系統執行排定的任務和外部時間定時的順序。任務之間和任務同計算機之間的交互方式,以及外部時間的任意定時都使這種順序變得隨機。很多情況下,帶有競爭狀態的代碼會在數千次測試中返回相同的結果,但仍然可能會在運行時返回一個不同的結果。
對生產者/消費者設計模式的一個更有效的實現是使用通知器和隊列使數據傳輸保持同步。通知器在發出數據可用的通知時,將同時發送數據。使用通知器將數據從主循環傳送到從循環消除了和競爭狀態相關的問題。使用通知器還有同步的好處,因為數據可用時,主從循環都已完成定時,并準備實現一個良好的生產者/消費者設計模式。但是通知器不會緩沖數據,如果主循環在從循環讀取第一份數據之前發送另一份數據,那么原來那份數據就會被覆蓋并丟失。隊列類似于通知器。但它可以存儲多份數據,默認情況下,隊列按照FIFO(先進先出)的方式執行。因此,第一份插入隊列的數據,也是第一份從隊列中刪除的數據。在實時控制的連續音頻信號采集過程中,由于需要處理許多用戶界面的事件,為了不造成數據丟失,選擇隊列在各個循環之間傳遞數據,實現過程如圖1所示。
如圖1所示,在循環開始使用“獲取隊列引用”函數之前,隊列就已經創建完畢。生產者循環使用“元素入隊列”函數向隊列中添加數據。消費者循環使用“元素出隊列”函數從隊列中移除數據。消費者循環一直到隊列中的數據可用時才執行。
可見,在此生產者/消費者設計模式中,兩個循環均被同步為與生產者循環一致。消費者循環只在隊列中的數據可用時才執行。這樣就保證了消費者循環執行任務的連續性和高效性。并且,隊列用于循環之間的數據傳遞,創建全局可用的位于隊列中的數據,而且在添加新的數據到隊列時,避免了丟失數據的可能性。
2 實時控制的連續音頻信號采集系統
2.1 聲卡簡介
從數據采集的角度看,聲卡是一種音頻范圍內的數據采集卡,是計算機與外部模擬量環境聯系的重要途徑。一般聲卡都是由以下幾部分組成:聲音控制/處理芯片,功放芯片,聲音輸入/輸出端口等。
聲音控制/處理芯片是聲卡的核心,集成了采樣保持、A/D轉換、D/A轉換、音效處理等電路,它決定了聲卡的性能和檔次,基本功能包括對聲波采樣和回放控制、處理MIDI指令等,有的廠家還加進了混響、合聲、音場調整等功能。
功放芯片完成信號的功率放大以推動喇叭發聲工作。聲音輸入/輸出端口是音頻信號的輸入和輸出,它主要有外接端口和內接端口。外接端口有“SPK Out”喇叭輸出端口,“Wave Out(或Line Out)”線性輸出端口,“Line In"線性輸入端口,“MIC”麥克風輸入端口,還有MIDI端口,連接電子樂器以及連接游戲控制器。內接端口是內置的輸入/輸出端口,是CD音頻接口,通過3~4針的音頻線直接連接。Line In接口和MIC都可以用于外部音頻信號的輸入,只不過后者可接入較弱的信號,幅值大約為0.02~O.2 V,顯然這個信號較易受到干擾,因而常使用Line In,它可接入幅值約不超過1 V的信號。
市面上的聲卡主流都是16位的,聲卡的最高采樣頻率是44.1 kHz,民用的聲卡一般將采樣頻率設為4檔,分別為44.1 kHz,22.05 kHz,11.025 kHz和8 kH。與一般的數據采集卡不同,聲卡的D/A和A/D功能都是連續狀態的。
2.2 具體設計
根據聲卡的性能指標,將聲卡初始設置為雙聲遣、44 100 Hz采樣頻率、16位采樣精度。要使采集到的音頻信號達到逼真的效果,要求信號的采集過程保持連續,但實時控制要求程序對用戶界面的控件做出響立,這就在采集的連續性和對用戶的響應方面產生了矛盾。本音頻信號采集系統,運用生產者/消費者程序設計模式,很好地解決了這一矛盾,使生產者循環完成對用戶界面的響應,消費者循環完成音頻信號的采集任務,從而不僅提高了整個信號采集過程的效率,而且使采集的語音信號效果逼真。圖2是實際音頻信號采集系統前面板。
主要程序框圖如圖3所示,在循環開始前,使用“獲取隊列引用”函數創建消息隊列。生產者循環使用“元素入隊列”函數向隊列中添加數據。消費者循環使用“元素出隊列”函數從隊列中獲取消息并移除數據。
該設計模式允許消費者循環以固有速度采集信號的同時,生產者循環完成對用戶界面的響應,生產者循環中采用事件結構,事件結構的延時時間為100 ms,采用輪詢操作,處理用戶界面各個控件的響應,對信號采集進行實時控制,同時為了不影響消費者循環中信號采集的連續性,并不是每一個用戶事件都通過隊列產生消息,通知消費者循環重新配置信號采集,只有在聲卡配置參數(采樣點數、采樣率)發生改變時,生產者循環使用“發送通知”函數產生消息,以便通過“ 等待通知”函數通知消費者循環。
消費者循環內部是狀態機結構,在第一次循環時進入“SetUp”分支,進行聲卡的初始化配置,從下次循環開始,在其他控件發生改變而有關聲卡配置的參數不發生變化時,生產者循環不會產生消息隊列,消費者循環中在“daq”分支和“Wait”分支間進行,“Wait”分支僅檢查消息隊列中是否有消息,如果沒有轉“daq”分支進行數據采集,而不會進入聲卡配置的“SetUp”分支,這樣不僅保證了獨立的采集過程不受影響,而且由用戶界面引起的任何延時(如顯示對話框)都不會導致采集過程的循環操作產生延時,從而保證采集音頻信號的連續性。
在用戶改變聲卡配置參數發生時,生產者循環響應該事件,“元素入隊列”函數向隊列中添加消息,消費者循環“Wait”分支中的“元素出隊列”函數從隊列中移出消息,在下次循環時進入“Setup”分支進行聲卡參數配置,然后轉入“daq”分支繼續進行信號采集。在“daq”分支中除進行數據采集外,還對信號進行功率譜分析,并將信號保存在一個硬盤文件中。
通過大量實驗發現采用生產者/消費者設計模式設計的音頻信號采集系統能夠有效避免在采集過程中出現的聲音中斷和失真現象,較之以前基于其他模式的設計有一定的優勢。
3 結 語
在LabVIEW程序設計過程中,并行循環之問的數據傳遞必須進行妥善處理,否則就會出現死循環等預想不到的錯誤。該文介紹的生產者/消費者設計模式不僅使并行循環間傳遞數據的邏輯關系更加簡潔明了,使得程序的修改維護更加方便,而且大大提高了程序運行的效率。本文只是利用一個簡單的實時控制的連續音頻信號采集系統介紹了此模式的應用,闡明了這種設計模式的思想,在用LabVIEW設計如網絡通信程序等要求準確且響應速度快的實時控制程序時,生產者/消費者模式有很好的借鑒意義。