ปกติแล้วระบบเสียงบนลินุกซ์ ไม่ว่าจะใช้ ALSA หรือ OSS อนุญาตให้แอพพลิเคชันใช้งานได้เพียงตัวเดียวเท่านั้น เพราะเหตุนี้ หาก XMMS กำลัง playback ผ่าน ALSA แล้ว โปรแกรมอื่นๆ จะใช้ ALSA ไม่ได้ .. ที่จริงแล้วระบบเสียงทุกๆ โอเอสก็เป็นแบบนี้ล่ะครับ เพราะข้อจำกัดจริงๆ อยู่ที่ซาวด์การ์ดซึ่งเกือบทั้งหมดนี้มีชิปสังเคราะห์เสียงเพียงตัวเดียว .. เพื่อแก้ปัญหานี้ บนลินุกซ์จึงมีซอฟต์แวร์ที่เรียกกันว่าซาวด์เซิร์ฟเวอร์ เช่น aRTs ESD NAS หรือ JACK ทำหน้าที่เป็นตัวบริการแทนไดรเวอร์ โดยรับหน้าที่ในการมิกซ์เสียงเพื่อให้แอพพลิเคชันหลายๆ ตัวใช้งานระบบเสียงได้พร้อมๆ กัน .. อย่างไรก็ตาม ข้อเสียของซาวด์เซิร์ฟเวอร์ที่พบในปัจจุบันคือคุณภาพเสียงจะลดลงเมื่อแอพพลิเคชันใช้งานกันหลายตัว โดยเฉพาะการ playback ในอัตราแซมปลิ้งที่ต่างๆ ไปจากความสามารถของซาวด์การ์ด อีกทั้งโปรแกรมต้องเขียนให้สนับสนุนซาวด์เซิร์ฟเวอร์นั้นๆ ด้วย
ที่จริงแล้ว หากใช้ ALSA แล้ว ไม่จำเป็นต้องมีซาวด์เซิร์ฟเวอร์ แอพพลิเคชันก็สามารถสั่ง playback เสียงพร้อมๆ กันได้ โดยใช้ Dmix plugin
ใช้งาน Dmix
Dmix เป็น PCM direct stream mixing plugin ของ ALSA ปลั๊กอินนี้ทำหน้าที่มิกซ์เสียงเพื่อให้แอพพลิเคชันสั่ง playback เสียงได้พร้อมๆ กัน .. Dmix ฝังอยู่ใน libasound มาตั้งแต่ ALSA เวอร์ชัน 0.9 กว่าๆ แล้ว เพียงแต่ไม่ค่อยมีใครรู้และเอามาใช้งานมากนัก ข้อดีของ Dmix คือมันไม่ได้ใช้โมเดลแบบไคลเอนด์/เซิร์ฟเวอร์เหมือนซาวด์เซิร์ฟเวอร์ แต่ใช้วิธีรับข้อมูลแล้วเขียนลงบัฟเฟอร์ของซาวด์การ์ดโดยตรงผ่านทาง DMA ผลคือ Dmix ไม่มีข้อจำกัดเรื่องจำนวนไคลเอนด์ และได้คุณภาพเสียงที่ดี
ในขั้นพื้นฐานที่สุด การใช้งาน Dmix ทำได้โดยระบุดีไวซ์ของ ALSA เป็น Dmix plugin เช่น โปรแกรม aplay ใช้พารามิเตอร์ -D กำหนดดีไวซ์ที่ต้องการใช้ ลองเปิดเทอร์มินัลสองตัว แล้วเรียกใช้ aplay ตามข้างล่างนี้:
$ aplay -Dplug:dmix file.wav
ควรจะได้ยินเสียงจาก file.wav สองเสียงพร้อมกัน
หรือ XMMS ก็สามารถใช้ ALSA plugin แล้วระบุดีไวซ์เป็น plug:dmix ได้เช่นกัน
อย่างไรก็ตาม การใช้งาน Dmix โดยตรงนี้มักจะให้คุณภาพเสียงที่ไม่ดีมากนัก และมักจะมี noise การใช้งานจริงจึงมักจะสร้างดีไวซ์ PCM ขึ้นมาใหม่ โดยสร้างหรือแก้ไขไฟล์ ~/.asoundrc ตามนี้
pcm.intel8x0 { type dmix ipc_key 1313 slave { pcm "hw:0,0" period_time 0 period_size 1024 buffer_size 8192 rate 44100 } }
อธิบายคร่าวๆ
~/.asoundrc เป็นคอนฟิกไฟล์ของ libasound นอกเหนือจากคอนฟิกค่าปริยายใน /usr/share/alsa/alsa.conf เราสามารถสร้างดีไวซ์ PCM ของ ALSA ขึ้นมาใหมได้โดยการกำหนดไว้ในไฟล์นี้ จากตัวอย่างนี้ผมสร้างดีไวซ์ PCM ของ ALSA ในชื่อ “intel8x0” ชื่อนี้จะตั้งเป็นอะไรก็ได้ครับ ขอเพียงไม่ซ้ำกับที่กำหนดไว้ก่อนหน้านี้เท่านั้น
- ผมตั้งเป็น intel8x0 ตามไดรเวอร์ของ i830 AC’97
- ชนิดของ PCM เป็น dmix หมายความว่า PCM ตัวนี้จะใช้ Dmix plugin เป็นตัว playback ส่วนของ
- slave มีไว้กำหนดดีไวซ์ที่ intel8x0 ทำงานครอบอยู่ จากตัวอย่างนี้กำหนดเป็น
- ดีไวซ์ PCM “hw:0,0” อ้างอิง ฮาร์ดแวร์ PCM (บนซาวด์การ์ด) ไอดี 0 พอร์ต 0
- period_time ขนาดของข้อมูลที่ส่งเข้า/ออกซาวด์การ์ด หน่วยเป็น usec ค่าปริยายจะส่งข้อมูลเข้าซาวด์การ์ดเป็นจังหวะทุก 125 msec (ค่าปริยาย = 125000 usec) กำหนดเป็น 0 เพื่อ override ค่าปริยาย
- period_size ขนาดของข้อมูลที่ส่งเข้า/ออกซาวด์การ์ด หน่วยเป็นไบต์ ค่าที่กำหนดต้องเป็นสองยกกำลัง n กำหนดมากหรือน้อยไปจะมี noise รบกวน
- buffer_size กำหนดขนาดของบัฟเฟอร์ กำหนดมากไปอาจจะทำให้มี latency สูง กำหนดน้อยไปก็จะทำให้เสียงขาดช่วง
- rate อัตราแซมปลิ้ง ที่ 44.1 kHz (ค่าปริยาย = 48 kHz)
ออปชันอาจจะมากหรือน้อยกว่านี้ก็ได้ ค่า period_size กับ buffer_size ไม่จำเป็นต้องเป็นค่า 1024/8192 เสมอไป เพราะขึ้นกับซาวด์การ์ดและชิป PCM ด้วย ต้องลองปรับกันเอาเองครับ
หลังจากได้ดีไวซ์ PCM ตัวใหม่แล้วทีนี้เราก็สามารถอ้างอิงดีไวซ์นี้เพื่อใช้ playback เช่น
$ aplay -Dintel8x0 file.wav
และ หากต้องการกำหนดให้ใช้ดีไวซ์ Dmix โดยปริยาย สามารถทำได้โดยเพิ่มบรรทัดต่อไปนี้ ลงไปใน %HOME/.asoundrc
pcm.!default { type plug slave.pcm "intel8x0" }
กรณีนี้แอพพลิเคชันที่ตั้งดีไวซ์ PCM เป็น default ไว้แล้ว เช่น xine และ xmms ก็จะใช้งาน Dmix โดยอัตโนมัติ โปรแกรมอื่นๆ ก็เพียงกำหนดให้ใช้ดีไวซ์ที่เป็น Dmix เท่านั้น เช่น กรณีของ mplayer/gmplayer หากใช้ ALSA จะ playback ออก hw:0,0 โดยตรง เราสามารถกำหนดดีไวซ์ที่ต้องการ playback ได้โดยใช้ออปชัน -ao เช่น
$ mplayer -ao alsa9:intel8x0 file.mpg
หรือ
$ mplayer -ao alsa9:default file.mpg
หากจะตั้งถาวรก็ตั้งในไฟล์ ~/.mplayer/config เช่น
ao=alsa9:intel8x0
หรือในกรณีของ gaim ซึ่งไม่สนับสนุน ALSA โดยตรง ก็สามารถใช้โปรแกรม aplay แทนได้ โดยเลือก
Preferences -> Sounds เลือก Method เป็น Command กรอกในช่อง Sound command เป็น
$ aplay -Dintel8x0 %s
โดยสรุปคือ
ถ้าตั้งดีไวซ์ได้ ก็ให้ตั้งเป็นดีไวซ์ที่มี type เป็น Dmix หรือมี slave เป็น Dmix
ถ้ากำหนดคำสั่งในการ playback ได้ ให้ใช้ aplay โดยกำหนดให้ใช้ดีไวซ์ที่มี type เป็น Dmix หรือมี slave เป็น Dmix
ปัญหาที่เจอเมื่อใช้ Dmix
เวลานี้มีอยู่สองอย่างคือ
- xmms อาจจะหยุด playback กลางคัน โปรแกรมไม่แครช กด play อีกครั้งก็จะเริ่ม playback ได้ปกติ .. ตอนนี้ยังไม่มีทางแก้ครับ
- mplayer หาก playback ไฟล์ที่อัตราแซมปลิ้งสูงหรือต่ำกว่าที่ตั้งไว้ใน .asoundrc เสียงจะเพี้ยน (xine ไม่มีปัญหาตรงจุดนี้) ทางแก้คือกกำหนดให้ใช้ดีไวซ์ที่เหมาะกับการ playback เช่น กรณีที่ playback ไฟล์ที่มีอัตราแซมปลิ้ง 44.1 kHz อาจใช้ -ao alsa9:default หรือ -ao alsa9:intel8x0 แต่ถ้าไฟล์มีอัตราแซมปลิ้งที่ 48 kHz ให้ใช้ -ao alsa9:hw เป็นต้น
.. ลองใช้งานกันดูนะครับ :)