วันเสาร์ที่ 26 กุมภาพันธ์ พ.ศ. 2554

การสร้างสัญญาณ Decaying Sinusoid ด้วยตัวกรองดิจิตอลโดยใช้ pd

แบบจำลองของเสียงจากเครื่องดนตรีแบบหนึ่งคือ Decaying Sinusoid ซึ่งก็คือสัญญาณตระกูลไซนูซอยด์ที่มีขนาดลดลงด้วยอันดับเอกโพเนนเชียลเมื่อเวลาผ่านไป สัญญาณลักษณะนี้สามารถเขียนเป็นสมการได้
amath y(t) = A*e^{-b*t}*sin( omega_{c} * t ) endamath
เมื่อ amath A endamath คือขนาดของสัญญาณ amath a endamath คืออัตราการลดทอน amath omega_{c} endamath คือความถี่มีหน่วยเป็น rad/sec และ amath t endamath คือเวลา
สัญญาณ Decaying Sinusoid (เส้นสีแดงและเส้นสีเขียวเป็นเพียงเส้นนำสายตาเท่านั้น)
กลยุทธ์การสังเคราะห์เสียงลักษณะนี้ก็คือการใช้ตัวกรองที่มีผลตอบสนองอิมพัลส์ (Impulse Response) ที่มีหน้าตาแบบนี้เลย คือถ้าใส่อิมพัลส์เข้าไป ให้ตัวกรองส่งสัญญาณหน้าตาแบบนี้ออกมา ซึ่งเราสามารถสร้างตัวกรองดังกล่าวได้โดยใช้กรรมวิธีการออกแบบตัวกรองดิจิตัลแบบอิมพัลส์ไม่เปลี่ยนแปลง (Impulse Invariant Method)

ด้วยวิธี Impulse Invariant Method เราสามารถเขียนผลตอบสนองของตัวกรองดิจิตัลในรูปแบบสัญญาณดิสครีตได้ดังนี้
amath y(n) = A*e^{-k*n}*sin(omega_{d}*n) endamath
เมื่อ amath k endamath เป็นอัตราลดทอนที่แปลงมาจาก amath b endamath amath omega_{d} endamath เป็นความถี่ในโดเมนดิสครีตมีหน่วยเป็น rad/sample และ amath n endamath คือ index ของสัญญาณดิสครีต

ตัวกรองที่มีผลตอบสนองอิมพัลส์เป็นสัญญาณนี้คือตัวกรองที่มี Transfer Function - H(z) เป็น z-Transform ของสัญญาณนี้นั่นเอง ซึ่งจากตารางการแปลง z ทำให้เราทราบว่า
amath A*e^{-k*n}*sin(omega_{d}*n) -> (e^{-k}*sin(omega_{d})*z^{-1})/(1-2*e^{-k}*cos(omega_{d})*z^{-1}+e^{-2*k}*z^{-2}) endamath
เราสามารถสร้างตัวกรองนี้ใน puredata ได้โดยตรงโดยใช้ออบเจ็ค fexpr~ สร้างสมการผลต่าง (Difference Equation) ไดัเป็น
amath y(n) = e^{-k}*sin(omega_{d})*x(n-1)+2*e^{-k}*cos(omega_{d})*y(n-1)-e^{-2*k}y(n-2) endamath
และต่อเป็นแพตช์ใน puredata ได้ดังรูป

ซึ่งเราสร้างขึ้นมาเป็น sub-patch ให้รับอินพุตได้ 4 ค่าคือ
  1. อิมพัลส์ (x1 ใน fexpr~) เป็นตัวกระตุ้นตัวกรอง ซึ่ง puredata patch สำหรับอิมพัลส์สามารถดูได้จากผลงานเมื่อคราวก่อน
  2. อัตราการลดทอน (f2 ใน fxpr~ - หมายถึงอินพุตที่ 2 และเป็นตัวแปรประเภท Float) amath e^{-k} endamath
  3. ความถี่ในโดเมนดิสครีต หน่วยเป็น rad/sample (ระบุผ่าน f3 - amath cos(omega_{d}) endamath และ f4 - amath sin(omega_{d}) endamath)
  4. อัตราชักตัวอย่าง (Sampling Rate -fs) ไว้ใช้คำนวณค่า amath omega_{d} endamath ก่อนส่งเข้าไปใน fexpr~
ในโอกาสต่อไปจะนำเสนอการนำ Decaying Sinusoid ไปสร้างเสียงสังเคราะห์ที่ซับซ้อนมากขึ้น

วันอังคารที่ 8 กุมภาพันธ์ พ.ศ. 2554

การสร้าง Impulse (Discrete) ใน pd เพื่อใช้ทดสอบตัวกรอง

ผมหัดใช้ pd มาได้สักพักแล้ว ตอนนี้กำลังทำโครงงานที่สอง (เลยนึกได้ว่าไม่เคยบันทึกโครงงานแรกลงในบล๊อกเลย) ในโครงงานนี้เราจะสร้างตัวกรอง (Filter) เพื่อสังเคราะห์สัญญาณเสียงขึ้นมา ซึ่งตัวกรองจะทำงานได้ต้องมีอินพุต และอินพุตที่เราจะใช้นั้นเป็นอิมพัลส์ (Impulse) ในดิสครีตโดเมน

ใน pd-extended นั้นจะมีออบเจ็ค dirac~ ให้ใช้อยู่ แต่เนื่องจากผมใช้เดเบียนซึ่งใน Repository มีแต่ pd-vanilla ซึ่งไม่มีออบเจ็ค dirac~ ให้ใช้ ก็ต้องสร้างเอง

การสร้างได้แนวทางมาจาก http://www.mail-archive.com/pd-list@iem.at/msg12771.html และหลังจากลองผิดลองถูกมาได้สักพัก ก็สามารถสร้าง Discrete Impulse ขึ้นมาจนได้ดังรูป
หลักการทำงานก็คือ
  1. รับข้อความ \$1 0 มาจาก inlet เมื่อ \$1 เป็นตัวแปรที่ส่งเข้ามาเพื่อใช้เป็นขนาดของอิมพัลส์
  2. ส่งข้อความไปให้ vline~ สร้างสัญญาณเป็น \$1 ทันทีที่ได้รับข้อความ
  3. หลังจากนั้น ข้อความ \$1 0 จะส่งทริกเกอร์ไปยังการคำนวณคาบเวลา T=1/fs (ในที่นี้ใช้ 1.5/fs แทน เผื่อไว้กันเหนียว)
  4. สร้างข้อความ 0 0 \$1 เมื่อ \$1 ระยะเวลาเป็นหน่วยมิลลิวินาทีที่รอก่อนที่ vline~ จะสั่งให้ตั้งค่าเป็นศูนย์ เราพยายามจะตั้งให้ได้ 1 Sample=1/fs พอดี แต่เพื่อผลที่แน่นอนใน Patch นี้เราเลยเลือกใช้เป็น 1.5/fs แทน
  5. ส่งข้อความไปให้ vline~ เพื่อตั้งค่าให้เป็น 0
  6. ส่งออกเป็น Stream ไปที่ outlet~
ทดลองแล้วใช้ได้ผลดี ถ้าต้องการตรวจสอบผล ให้เพิ่มออบเจ็ค print~ ไปที่เอาต์พุตของ vline~ และให้รับ bang มาจากข้อความไหนก็ได้ใน Patch ด้วย จะเห็นผลลัพธ์ดังรูปต่อไปนี้
ต่อไปนี้ก็สามารถทดสอบตัวกรองต่าง ๆ ได้ ซึ่งถ้ามีอะไรน่าสนใจก็จะนำมาเสนอต่อไป