linux下mono播放PCM音訊
測試環境:
Ubuntu 14
MonoDevelop
CodeBlocks
1、建立一個共享庫(shared library)
這裡用到了linux下的音訊播放庫,alsa-lib。 alsa是linux下的一個開源專案,它的全名是Advanced Linux Sound Architecture。它的安裝命令如下:
sudo apt-get install libasound2-dev
使用 Coceblocks 建立一個 shared library 專案,命名為libTest2,程式語言選擇C。在main中加入下程式碼:
1 #include <alsa/asoundlib.h> 2 #include<stdio.h> 3 4 5 snd_pcm_t *handle; 6 snd_pcm_sframes_t frames; 7 8 9 int PcmOpen() 10 { 11 12 if ( snd_pcm_open(&handle, "hw:0,0", SND_PCM_STREAM_PLAYBACK, 0) < 0 ) 13 { 14 printf("pcm open error");15 return 0; 16 } 17 18 if (snd_pcm_set_params(handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 8000, 1, 500000) < 0) //0.5sec 500000 19 { 20 printf("pcm set error"); 21 return 0;
22 } 23 24 return 1; 25 } 26 27 28 29 void Play(unsigned char* buffer, intlength) 30 { 31 frames = snd_pcm_writei(handle, buffer, length); 32 if(frames < 0) 33 { 34 frames = snd_pcm_recover(handle, frames, 0); 35 } 36 } 37 38 39 40 41 int PcmClose() 42 { 43 snd_pcm_close(handle); 44 return 1; 45 }
在編譯的時候,記得連結alsa-lib庫。具體方法是在codeblocks的編譯對話方塊中,找到linker settings選項,在Other linker options中輸入:-lasound。
如圖所示:
當然,也可以手工編譯。cd 進main.c所在的目錄,執行以下命令:
gcc -o main.o -c main.c gcc -o libTest1.so -shared main.o -lasound
2、在mono中呼叫共享庫
與.net呼叫動態庫一樣,使用DllImport特性來呼叫。關於mono呼叫共享庫,mono官方有一篇文章介紹得很詳細:《Interop with Native Libraries》。
使用monoDevolop建立一個控制檯專案,並將上一步中生成的libTest1.so檔案拷貝到/bin/Debug下。
在Program.cs檔案中輸入以下程式碼:
using System; using System.Runtime.InteropServices; using System.IO; using System.Threading; namespace helloworld { class MainClass { public static void Main(string[] args) { Console.WriteLine("the app is started "); PlayPCM(); Thread thread = new Thread(new ThreadStart(PlayPCM)); thread.Start(); while (true) { if (Console.ReadLine() == "quit") { thread.Abort(); Console.WriteLine("the app is stopped "); return; } } } /// <summary> /// Plaies the PC. /// </summary> static void PlayPCM() { using (FileStream fs = File.OpenRead("Ireland.pcm")) { byte[] data = new byte[4000]; PcmOpen(); while (true) { int readcount = fs.Read(data, 0, data.Length); if (readcount > 0) { Play(data, data.Length); } else { break; } } PcmClose(); } } [DllImport("libTest1.so")] static extern int PcmOpen(); [DllImport("libTest1.so")] static extern int Play(byte[] buffer, int length); [DllImport("libTest1.so")] static extern int PcmClose(); } }
為了便於測試,附件中包含了一個聲音檔案,可以直接使用這個聲音檔案。
3、有關PCM檔案的一些簡要說明
附件中的Ireland.pcm,採用的是PCMU編碼,取樣率為8000Hz,取樣深度為1位元組,聲道數為1。這些對應於snd_pcm_set_params函式,這個函式用於以較簡單的方式來設定pcm的播放參數。要正確地播放聲音檔案,必須使PCM的引數與聲音檔案的引數一致。