วันเสาร์ที่ 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 ด้วย จะเห็นผลลัพธ์ดังรูปต่อไปนี้
ต่อไปนี้ก็สามารถทดสอบตัวกรองต่าง ๆ ได้ ซึ่งถ้ามีอะไรน่าสนใจก็จะนำมาเสนอต่อไป

วันอังคารที่ 18 มกราคม พ.ศ. 2554

การเขียนวิทยานิพนธ์ ม.ข. ด้วย LaTeX - สร้างสารบัญ

ข้อกำหนดหนึ่งของวิทยานิพนธ์บัณฑิตศึกษา มหาวิทยาลัยขอนแก่นคือสารบัญ
ข้อกำหนดคือ
  1. สารบัญ และส่วนประกอบอื่น ๆ เช่น กิตติกรรมประกาศ มีศักดิ์ศรีเทียบเท่าบท ดังนั้นหัวข้อของสารบัญจึงใช้หัวข้อของบท แต่ไม่ต้องมีเลขบท คือเป็นตัวอักษรแบบตัวหนาขนาด 18 พอยต์ (Bold 18 points) อยู่กึ่งกลางหน้ากระดาษ
  2. หากสารบัญมีมากกว่าหนึ่งหน้า หน้าต่อ ๆ ไปของสารบัญจะต้องขึ้นหัวข้อว่า "สารบัญ (ต่อ)" ด้วยอักษรตัวหนาขนาด 18 พอยต์เช่นเดียวกัน (ข้อนี้ไม่มีคำสั่งเป็นลายลักษณ์อักษร แต่ตัวอย่างที่มีให้เป็นแบบนี้ และวิทยานิพนธ์ทุก ๆ เล่มที่ผมเข้าถึงได้ ก็เป็นแบบนี้)
  3. เนื้อสารบัญควรบอก บทที่ ชื่อบท และเลขหน้าของบทนั้น ๆ เริ่มตั้งแต่บทคัดย่อ จนไปจบที่ประวัติผู้เขียนเป็นรายการสุดท้าย ใช้อักษรแบบธรรมดาขนาด 14 พอยต์ (Normal 14 points)
  4. หัวข้อย่อยของแต่ละบทนั้น แสดงลึกไม่เกิน 1 ระดับ คือสารบัญจะแสดงรายละเอียดถึง 1.1 หมายถึง บทที่ 1 หัวข้อที่ 1 เท่านั้น จะไม่แสดงรายละเอียดถึง 1.1.1
  5. หัวข้อย่อยควรจัดให้ตรงกับบท (ไม่บังคับ แต่ตัวอย่างเป็นแบบนี้)
  6. เลขลำดับของหัวข้อย่อย จะมีหรือไม่มีก็ได้
  7. ระยะห่างระหว่างชื่อบท หรือหัวข้อสารบัญ ถึงบรรทัดแรกของสารบัญ ให้เว้น 2 บรรทัด (ของอักษรขนาดกี่พอยต์?)
ค้นไปค้นมา พบว่าไม่ต้องเขียนอะไรมาก เอา แพคเกจที่มีคนทำไว้แล้วมาใช้ก็ได้ แพคเกจที่หยิบมาใช้คือ titletoc ซึ่งติดตั้งมาพร้อมกับ titlesec ซึ่งอยู่ในแพคเกจเดเบียน texlive-latex-extra

สิ่งที่ต้องใช้ใน preemble ก็คือ เรียกคลาสที่จำเป็นขึ้นมา
\RequirePackage{titletoc}
\RequirePackage{ifthen}
\RequirePackage{lineno}

ตั้งค่าความลึกของหน้าสารบัญใหม่เป็น 1 (คือลงลึกแค่ชั้นเดียว) และตั้งค่าคำสั่ง \tableofcontents ใหม่
\setcounter{tocdepth}{1}
\renewcommand\tableofcontents{%
% Header of the first page of the TOC
\chapter*{\contentsname\@mkboth{\MakeUppercase\contentsname}
{\MakeUppercase\contentsname}}%
\begin{flushright}
\textbf{หน้า}
\end{flushright}

% Counter for tocitem
\newcounter{tocitem}
\setcounter{tocitem}{0}

% Turn on the linenumber counts, but do not want to display it.
\modulolinenumbers[50]
\linenumbers[1]
\@starttoc{toc}%
\setcounter{tocitem}{0}
\clearpage
}

สร้างคำสั่งใหม่สำหรับตรวจสอบว่าบรรทัดปัจจุบัน หรือ จำนวนหัวข้อที่แสดงในสารบัญเกินค่าทึ่กำหนดหรือยัง หากเกินแล้วให้ตัดขึ้นหน้าใหม่ รีเซตตัวนับ tocitem รีเซตตัวนับบรรทัดใหม่ และเขียนหัวของหน้าสารบัญใหม่ (เช่น สารบัญ (ต่อ) ในกรณีนี้)
\newcommand{\tocheadcont}[3]{
\ifthenelse{#1>32 \OR #2>32}{
%Should be a newpage here.
\pagebreak[4]
\resetlinenumber[1]
\setcounter{tocitem}{0}
\begin{ċenter}
{\Large \textbf{#3 (ต่อ)} }
\end{center} 
\begin{flushright}
\textbf{หน้า}
\end{flushright}
}{}
}

การจัดรายการสารบัญโดยใช้คำสั่ง \titlecontents จากแพคเกจ titletoc
% tocitem format for chapter
\titlecontents{chapter}[0mm]
{\stepcounter{tocitem}\tocheadcont{\thelinenumber}{\thetocitem}{สารบัญ}}
{\chaptername\hspace{1ex}\thecontentslabel\hspace{2mm}}
{}{\hfill \contentspage}

% tocitem format for section
\titlecontents{section}[0mm]
{\stepcounter{tocitem}\tocheadcont{\thelinenumber}{\thetocitem}{สารบัญ}}
{\hspace{\firstindentlength}\thecontentslabel\hspace{2mm}}{\hspace{\firstindentlength}\thecontentslabel\hspace{2mm}}
{\hfill \contentspage}

ผลลัพธ์ที่ได้แสดงในรูป


กล่าวโดยสรุปเราใช้
  • \titlecontents จากแพคเกจ titletoc เพื่อจัดรูปแบบของรายการสารบัญ
  • \thelinenumber จากแพคเกจ lineno เพื่อนับบรรทัดในหน้า
  • \newcounter{tocitem} สร้างตัวนับรายการสารบัญ
  • \ifthenelse จากแพคเกจ ifthen เพื่อตรวจเงื่อนไข
อันที่จริงเราอาจใช้ทางอื่นในการสร้างหัวสารบัญในหน้าถัดไปได้ เช่นเอาหัวสารบัญไปใส่ในส่วนหัวของหน้าแล้วจัด Margin ใหม่ก็ได้ แต่ผมไม่ได้คิดถึงทางออกนี้จนกระทั่งแก้ปัญหามาทางนี้เกือบเสร็จแล้ว หากใครมีทางเลือกอื่น ๆ เพื่อจัดหน้าสารบัญสำหรับวิทยานิพนธ์ ม.ข. ก็จะขอแบ่งประสบการณ์ด้วยครับ

วันอาทิตย์ที่ 12 ธันวาคม พ.ศ. 2553

3BB กับ Debain

วันนี้ติดตั้ง 3BB ที่บ้านเรียบร้อย บริการรวดเร็วทันใจ ผู้รับเหมาที่มาติดตั้งก็นิสัยดีมาก คือทำงานไม่ชุ่ยและแสดงให้เห็นว่าพยายามจะให้ผลงานออกมาเรียบร้อยถูกใจลูกค้า

สมัครเมื่อวาน ติดตั้งเสร็จวันนี้ เร็วทันใจดีจริง

แต่เอ...คู่มือที่ให้มามีแต่สำหรับ Window นะนี่ อ่ะ ไม่เป็นไรระบบพอจะคุ้น ๆ อยู่

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

ดังนั้นใช้ ifconfig ปลุก eth0 ให้ตื่นซะก่อน แปลงร่างเป็นผู้มีอภิสิทธิ์ในระบบซะแล้วก็

> ifconfig eth0 up

หลังจากนั้น ก็ให้ DHCP ของ 3BB (หรือว่าของเราเตอร์ก็ไม่รู้ล่ะ) กำหนด IP ให้เรา

> dhclient eth0

ตอนนี้ควรจะใช้การได้แล้ว จะลอง ping ลอง host ดูว่าเชื่อมต่อกับเน็ตเวิร์กแล้วหรือยังก็ได้เช่น

> host google.com

ถ้าแสดง IP ของ google.com มาได้ก็แสดงว่าใช้ได้แล้ว เคยถามที่จุดให้บริการเรื่อง proxy เขาว่าไม่ต้องใช้ ก็ให้เอา proxy ของ browser ออกซะ แล้วก็ลองใช้อินเตอร์เนตดู   

ทีนี้ล่ะ Debian ของผมมีปัญหา เข้าบางเว็บไม่ได้ แต่เครื่องของแฟนเข้าได้!!?? คิดไปคิดมา เฮ้ย เราเคยเจอปัญหาอย่างนี้มาหนหนึ่งแล้วนี่นา กับ True ของน้องชายไง สาเหตุอันเนื่องมาจาก DNS ที่เราใช้มันใช้ไม่ได้ หรือมันใช้ไม่ดี ยังไงก็ไม่ทราบ เอ้า! ลองเปลี่ยน DNS ดู

> vi /etc/resolve.conf

แล้วแก้ไข nameserver ให้เป็นค่าอื่นที่เราคิดว่าใช้ได้ เช่น DNS ของ กูเกิลเป็นต้น

อย่างไรก็ตามผมก็ยังอยากรู้เหมือนกันว่า  DNS ของ 3BB ที่ถูกต้อง ควรตั้งเป็นค่าไหนกันแน่ เพราะค้นจากเว็บ จาก FAQ จาก ฯลฯ ก็ไม่พบข้อมูลที่เป็นทางการสักที ก็ต้องใช้ DNS ของกูเกิลไปก่อน หากมีใครทราบโปรดอนุเคราะห์ด้วยเถอะ ไหน ๆ ก็เสียเงินให้เขาไปแล้วอยากใช้ให้คุ้ม ไม่อยากไปใช้ที่อื่น

ป.ล. ผมเองก็จะถามไปที่ 3BB เหมือนกัน แต่ว่าไม่ค่อยแน่ใจว่าเขาจะเข้าใจคำถามของผมหรือเปล่าน่ะสิ เขาอาจจะถามกลับมาเรียบ ๆ ก็ได้ว่า ก็แล้วทำไมพี่ไม่ใช้ Window ล่ะ (ไม่ฮา) 

วันจันทร์ที่ 8 พฤศจิกายน พ.ศ. 2553

กลับมาแล้ว แต่กว่าจะกลับมาได้ เฮ้อ...

คอมพิวเตอร์คู่ใจพังไปได้ 2 เดือนแล้ว...ก็เป็นคอมพ์เครื่องนี้แหละครับ ที่ลง Debian ไว้ ใช้เขียนเอกสารประกอบการสอนในวิชาคณิตศาสตร์วิศวกรรม 4 (สมการอนุพันธ์) และวิชากรรมวิธีเชิงตัวเลข โดยใช้ Beamer และใช้ทำงานอดิเรกบน Linux ต่าง ๆ ที่เอามาเขียนลงบล๊อก

ดังนั้นเมื่อคอมพ์เครื่องนี้หมดเวลาของมันลงไป ผมก็ห่างหายไปจากงานอดิเรกต่าง ๆ บน Linux

ตอนนี้เพิ่งจะได้เครื่องเก่าของน้องชายมาใช้ ก็ติดตั้ง Debian เสร็จไปเมื่อสุดสัปดาห์ที่ผ่านมา เป็นการติดตั้ง Debian ที่อาจพอจะเปรียบเทียบได้กับการลุยป่าด้วยมีดพับเล่มเดียวก็ได้มั้ง คือสำหรับคนอ่อนหัดอย่างผม เส้นทางนี้ก็ถือว่าโหดเหมือนกัน คงไม่โอเวอร์ไปหรอก ฮิ ฮิ

กล่าวคือ ติดตั้งจาก CD No. 1 ของ Debian โดยที่เครื่องไม่ได้ต่ออินเตอร์เนตไว้ครับ อันที่จริงในเว๊บเขาก็ว่ามันทำได้ไม่น่าจะยากนะ แต่พอผมติดตั้งเสร็จ ตัวเลือกตอนติดตั้งนั้นมีเพียงตัวเลือกเดียวที่บังคับให้เลือกเลยคือ Base System ซึ่งไม่มี X ไม่มี Gnome

พอติดตั้งเสร็จก็...เอาล่ะซิ เราไม่ได้คุ้นเคยกับ Command Line เสียด้วย ทำไงดี!

ปรากฏว่าพอพยายามลองรัน apt-get ดู เหมือน ๆ มันจะเรียกอ่าน CD แฮะ เลยเอา CD ใส่เข้าไปแล้วลองติดตั้ง gnome ดู ปรากฏว่ายังใช้ไม่ได้ คิดว่าสาเหตุเป็นเพราะผมเรียกชื่อแพคเกจไม่ถูก จำชื่อ แพคเกจที่จำเป็นไม่ได้

งั้นเอาใหม่ ใช้ apt-get ไม่ได้ ใช้ aptitude ก็ได้ (ฟะ) ตัว aptitude ก็ช่วยได้คือมันจะแสดงรายการ แพคเกจต่าง ๆ ให้ เราก็เลือกหลัก ๆ ก็มี gnome นี่แหละ แล้วก็เช็คให้มั่นใจว่าได้เลือกให้ติดตั้ง gdm3 เรียบร้อยแล้วหรือยัง ถ้ายังต้องเลือกด้วย เพราะตัวนี้จะพาเราเข้ามาใน gnome ได้

เมื่อติดตั้ง gnome จาก CD ได้ ต่อไปก็ลองพยายามติดตั้ง wvdial ดู ปรากฏว่าใน CD#1 ไม่มี wvdial ต้องใช้เครื่องแฟน โหลด .deb ใส่ usb-drive มา พร้อมกับแพคเกจอื่น ๆ ที่เว็บ Debian ระบุว่าจำเป็น แล้วเราเช็คจาก aptitude ของเราแล้วไม่มีอยู่เดิม ใช้ dpkg ติดตั้ง wvdial ให้ได้

พอติดตั้ง wvdial ได้แล้วค่อยใช้ wvdial ติดต่อกับอินเตอร์เนต แล้วใช้ apt-get (หรือ aptitude) ก็แล้วแต่ ติดตั้งแพคเกจอื่น ๆ ที่เห็นว่าจำเป็น ในกรณีของผมซึ่งต่ออินเตอร์เนตด้วย GPRS ของ Nokia 31 Classic ได้ความเร็วดาวน์โหลดไม่เกิน 24 kbps นี้ใช้เวลาดาวน์โหลดแพคเกจที่ผมคิดว่าจำเป็นรวมทั้งสิ้นประมาณ 14 ชั่วโมง!

บัดนี้เครื่องพร้อมใช้งานแล้ว งานอดิเรกที่คั่งค้างไว้ทั้งหลายทั้งปวงก็จะได้เวลาสะสางกันเสียที

วันอังคารที่ 31 สิงหาคม พ.ศ. 2553

การเขียนบันทึกข้อความ (หนังสือราชการภายใน) โดยใช้ Latex (เพิ่มเติม)

คราวที่แล้วเขียนคลาสขึ้นมา (อันที่จริงก็เรียกแพคเกจหลายแพคเกจมาช่วย) สำหรับบันทึกข้อความ พบข้อบกพร่องดังนี้
  1. ผมใช้คำสั่ง \tabular สำหรับส่วนหัวของบันทึกข้อความ ทำให้หาก "เรื่อง" หรือ "เรียน" ซึ่งอยู่คอลัมน์ที่หนึ่งมีความยาวมาก เบอร์โทรศัพท์ของหน่วยงาน และวันที่ จะตกขอบขวา เพราะมันอยู่คอลัมน์ที่สองทั้งคู่
  2. คราวที่แล้ว ผมลืมสร้างคำสั่งสำหรับเขียนคำลงท้ายลงตำแหน่งที่เหมาะสม เช่น ด้วยความนับถือ เป็นต้น
  3. การทำบันทึกข้อความข้ามหน่วยงานภายในที่ถูกต้อง จะต้องให้หัวหน้าหน่วยงานรับทราบด้วยทุกครั้ง โดยการ เรียน [ใครก็แล้วแต่ที่อยู่นอกหน่วยงาน] ผ่าน [หัวหน้าหน่วยงานของท่าน] ซึ่งหัวหน้าหน่วยงานจะต้องลงนามรับทราบด้วย ในคลาสเดิมมันไม่มีคำสั่งสำหรับการนี้
ปัญหาที่ส่วนหัวของจดหมาย
ปัญหาแรก แก้ได้โดยใช้แพคแกจ multirow ซึ่งเรียกใช้โดยเพิ่ม
 \RequirePackage{multirow}
เข้าไปในคลาส แล้วแก้ไขคำสั่ง \opening เป็น
\newcommand{\openning}{%
\noindent \parbox{0.2\textwidth}{\raggedright{\includegraphics[width=20mm]{Tra-Khrut.eps}}} \hfill {\Large\bf บันทึกข้อความ} \hfill \parbox{0.2\textwidth}{\qquad}
\begin{tabular}{@{}ll}
{\bfส่วนราชการ} \@officeunit & {\bf โทร.} \@telephonenum \\
{\bfที่} \@unitid / \@memoreg & \@date \\
\multicolumn{2}{@{}l}{{\bfเรื่อง} \@title} \\
\multicolumn{2}{@{}l}{{\bfเรียน} \@letterto}
\end{tabular} % เว้นหนึ่งบรรทัดข้างล่างนี้ห้ามลบ

}
โปรดสังเกตคำสั่ง \multicolumn{2}{@{}l}{ข้อความที่จะใส่ในตาราง} ที่บรรทัดที่ 4 และ 5 จากบรรทัดสุดท้าย เลข 2 หมายถึงข้อความนี้อยู่ใน 2 คอลัมน์ พารามิเตอร์ {@{}l} หมายถึงชิดซ้ายโดยไม่เว้นขอบตาราง

ในโอกาสต่อไป หากทราบชัดเจนว่าหมายเลขโทรศัพท์และวันที่ควรอยู่ตำแหน่งใด ก็สามารถกำหนดได้โดยกำหนดความกว้างของตารางได้ทันที

ปัญหาเรื่องคำลงท้าย
ก็เพิ่มคำสั่งเข้ามาเลย เหมือนคำสั่งอื่น ๆ คือสร้างคำสั่งเพื่อรับคำลงท้ายจากเอกสาร tex เข้ามา
\newcommand*{\closingphrase}[1]{\def\@closingphrase{#1}}
แล้วก็กำหนดตำแหน่งให้เขียนในตำแหน่งที่ตรงกับการลงนามท้ายหนังสือ
\newcommand{\closing}{%
\vskip 0.5em
\parbox{0.3\textwidth}{\qquad}\parbox{0.7\textwidth}{\centering \@closingphrase}
}
ในอนาคต อาจเก็บตัวเลข 0.3 0.7 ที่เห็นข้างบนนี้ เป็นตัวแปร แล้วกำหนดค่าตัวแปรทีเดียวที่ต้นคลาสเลยก็น่าจะทำได้



ปัญหาที่การลงนามของหัวหน้าหน่วยงาน
เพิ่มคำสั่งเพื่อรับชื่อและตำแหน่งของหัวหน้าหน่วยงานโดย
\newcommand*{\approvalperson}[1]{\def\@approvalperson{#1}}
แล้วนำไปเขียนใต้ชื่อผู้ลงนามเอกสาร ให้ตำแหน่งตรงกันกับผู้ลงนาม เหมือนกับคำลงท้าย
\newcommand{\approvalsigned}{%
\vskip 3em
\parbox{0.3\textwidth}{\qquad}\parbox{0.7\textwidth}{\centering \@approvalperson}
}
ในส่วนของหัวหน้าหน่วยงานนี้เป็นตัวเลือก ถ้าไม่เรียกคำสั่ง \approvalsigned ก็ไม่มีอะไรเกิดขึ้น

ท่านสามารถดาวน์โหลดแฟ้มข้อมูลของคลาสที่ปรับปรุงแล้ว พร้อมตัวอย่างการใช้งาน ได้จากห้องทำงานของผมครับ

วันเสาร์ที่ 14 สิงหาคม พ.ศ. 2553

การเขียนบันทึกข้อความ (หนังสือราชการภายใน) โดยใช้ Latex

จากเดิมที่เคยทดลองใช้ fig2sty ไปเมื่อคราวก่อน พบว่าอาจเป็นปัญหาสำหรับคนที่ไม่ได้ใช้ xfig เป็นปรกติ (และอันที่จริง ก็ยังทำในส่วนของการลงนามไม่เสร็จด้วย) นอกจากนี้ ด้วยความที่ยังไม่เข้าใจระบบ margin ของเอกสารก็ทำให้ต้องทำ hardcode ในส่วนของการจัดตำแหน่งด้วย ซึ่งไม่น่าจะเป็นวิธีที่ดีเท่าไร

หลังจากได้อ่านเอกสารเกี่ยวกับการเขียน Latex Class ไปเมื่อคราวที่แล้ว เมื่อย้อนกลับมาดูปัญหาเดิม คือการเขียนบันทึกข้อความ (หนังสือภายใน) ก็พบว่าสามารถใช้ความรู้นั้นมาดัดแปลงได้ และแนวทางการแก้ปัญหาก็จะเป็นกรณีทั่วไปมากกว่า โดยเฉพาะไม่ต้องมีการลง hardcode ในเรื่องของตำแหน่งข้อความ (มากนัก)

สิ่งที่ต้องใช้ก็มี
  • การกำหนดตำแหน่งของส่วนหัวของบันทึกข้อความ ทำได้โดยคำสั่ง \parbox
  • การรับค่าต่าง ๆ เช่น เรื่อง เรียน ฯลฯ จากบันทึกข้อความมาสร้างส่วนหัว ทำได้โดยการสร้างคำสั่งใหม่
  • การใส่ภาพครุฑลงในเอกสาร ทำได้โดยใช้แพคเกจ graphicx
  • หากไม่ได้กำหนดไว้เป็นอย่างอื่น ให้ใช้ค่าปริยายของคลาส article ทั้งหมด
ทำให้ได้แฟ้มคลาสดังต่อไปนี้
%----------------------------------------
% officialmemoth.cls
% Official Internal Memo
% 2010-Aug-14 Kittiphong Meesawat ktphong (at) elec.kku.ac.th

% --- Class structure: identification part
% ---
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{officialmemoth}[2010/08/14 version 0.1 Official Internal Memo]

% Package ที่เรียกใช้งาน
\LoadClass[12pt,a4paper]{article}
\RequirePackage[left=25mm,right=25mm,top=25mm,bottom=25mm]{geometry}
\RequirePackage{graphicx}

% ตั้งค่า ย่อหน้า (Indent) ค่าขึ้นย่อหน้าใหม่ (Indentskip) และไม่ให้มีเลขหน้า (pagestyle)
\setlength{\parindent}{3em}
\setlength{\parskip}{1.5em}
\pagestyle{empty}

% คำสั่งเพื่อรับค่าต่าง ๆ ของบันทึกข้อความ
\newcommand*{\officeunit}[1]{\def\@officeunit{#1}}
\newcommand*{\unitid}[1]{\def\@unitid{#1}}
\newcommand*{\telephonenum}[1]{\def\@telephonenum{#1}}
\newcommand*{\memoreg}[1]{\def\@memoreg{#1}}
\newcommand*{\letterto}[1]{\def\@letterto{#1}}

% คำสั่ง \openning เพื่อสร้างส่วนหัวของบันทึกข้อความ
% ตำแหน่งต่าง ๆ เปลี่ยนแปลงได้ ถ้าทราบว่ามีข้อกำหนดตายตัวไว้อย่างไร
\newcommand{\openning}{%
\noindent \parbox{0.2\textwidth}{\raggedright{\includegraphics[width=20mm]{Tra-Khrut.eps}}} \hfill {\Large\bf บันทึกข้อความ} \hfill \parbox{0.2\textwidth}{\qquad}
\begin{tabular}{@{}ll}
{\bfส่วนราชการ} \@officeunit & {\bf โทร.} \@telephonenum \\
{\bfที่} \@unitid / \@memoreg & \@date \\
{\bfเรื่อง} \@title & \\
{\bfเรียน} \@letterto &
\end{tabular} % เว้นหนึ่งบรรทัดข้างล่างนี้ห้ามลบ

}

% คำสั่ง \undersigned เพื่อสร้างที่สำหรับเซ็นชื่อของผู้เขียนบันทึกข้อความ
% ตำแหน่งต่าง ๆ เปลี่ยนแปลงได้ ถ้าทราบว่ามีข้อกำหนดตายตัวไว้อย่างไร
\newcommand{\undersigned}{%
\vskip 3em
\parbox{0.3\textwidth}{\qquad}\parbox{0.7\textwidth}{\centering \@author}
}
%----------------------------------------  

เวลาใช้งานในแฟ้มเอกสาร Latex ก็เรียกใช้ class officialmemoth ดังนี้
%----------------------------------------  
\documentclass[12pt,a4paper]{officialmemoth}
\usepackage[thai]{babel}
\usepackage{thswitch}
% ใช้แบบอักษรกินรี ซึ่งเชื่อว่าคล้าย อังศณา มากที่สุด (ทำไมต้องเป็นอังศณาด้วยนะ?)
\usefont{LTH}{kinnari}{m}{n}

% ชื่อเรื่องหนังสือ
% ชื่อหน่วยงาน
% รหัสหน่วยงาน
% หมายเลขโทรศัพท์หน่วยงาน
\title{ทดสอบบันทึกข้อความ}
\officeunit{คณะวิศวกรรมศาสตร์ ภาควิชาวิศวกรรมไฟฟ้า}
\unitid{{\bf ศธ} 0514.4.1.4}
\telephonenum{12142 -- 44 ต่อ 712}

% เลขส่งหนังสือ (ปรกติมักเว้นว่างไว้ นอกเสียจากเราจะทราบเลขแน่นอน)
% วันที่ออกหนังสือ
\memoreg{}
\date{วันที่ 14 สิงหาคม 2553}

% ผู้รับหนังสือ และ
% ผู้เขียนหนังสือ (พร้อมตำแหน่ง โดยขึ้นบรรทัดใหม่ ถ้ามี)
\letterto{หัวหน้าภาควิชาวิศวกรรมไฟฟ้า}
\author{นายกิตติพงษ์ มีสวาสดิ์ \\ อาจารย์ประจำภาควิชาวิศวกรรมไฟฟ้า}

\begin{document}
% คำสั่ง \openning จะทำการสร้างส่วนหัวของบันทึกข้อความขึ้นมา
\openning
ทดสอบหัวกระดาษ ทดสอบหัวกระดาษ ทดสอบย่อหน้าและหัวกระดาษ ทดสอบหัวกระดาษและย่อหน้า ทดสอบย่อหน้า ทดสอบหัวกระดาษ ทดสอบหัวกระดาษ ทดสอบย่อหน้าและหัวกระดาษ ทดสอบหัวกระดาษและย่อหน้า ทดสอบย่อหน้า ทดสอบหัวกระดาษ ทดสอบหัวกระดาษ ทดสอบย่อหน้าและหัวกระดาษ ทดสอบหัวกระดาษและย่อหน้า ทดสอบย่อหน้า

ทดสอบหัวกระดาษ ทดสอบหัวกระดาษ ทดสอบย่อหน้าและหัวกระดาษ ทดสอบหัวกระดาษและย่อหน้า ทดสอบย่อหน้า ทดสอบหัวกระดาษ ทดสอบหัวกระดาษ ทดสอบย่อหน้าและหัวกระดาษ ทดสอบหัวกระดาษและย่อหน้า ทดสอบย่อหน้า ทดสอบหัวกระดาษ ทดสอบหัวกระดาษ ทดสอบย่อหน้าและหัวกระดาษ ทดสอบหัวกระดาษและย่อหน้า ทดสอบย่อหน้า

% คำสั่ง \undersigned จะทำการเขียนชื่อผู้เขียนบันทึก และตำแหน่ง (ถ้ามี)
\undersigned
\end{document}
%----------------------------------------  

และผลที่ได้จะมีหน้าตาแบบนี้ 

สิ่งที่ยังเป็นปัญหาอยู่ มีอยู่ 2 - 3 ประการด้วยกันคือ
  1. ผมไม่ทราบว่าตำแหน่งต่าง ๆ ในส่วนหัวของบันทึกข้อความ มีระบุไว้แน่นอนชัดเจนหรือไม่ เท่าที่เห็นใช้ Word Processor เขียนกัน ก็ใช้ Tab กะ ๆ เอา ตอนนี้เลยใช้ tabular environment ซึ่งทำให้ "วันที่" กับ "โทร." นั้นตรงกัน ถ้าไม่มีข้อเสนอแนะเป็นอย่างอื่น ก็จะคงไว้อย่างนี้
  2. ผมไม่ทราบว่าตำแหน่งของการลงชื่อท้ายบันทึกข้อความ มีระบุไว้แน่นอนชัดเจนหรือไม่ เท่าที่เห็นใช้ Word Processor เขียนกัน ก็ใช้ Tab กะ ๆ เอา ตอนนี้เลยใช้ parbox ช่วยกันพื้นที่ไว้ ถ้าไม่มีข้อเสนอแนะเป็นอย่างอื่น ก็จะคงไว้อย่างนี้
  3. รูปครุฑที่ใช้ เป็นรูปจาก wikipedia ซึ่งมีข้อความอธิบายว่า กฏหมายกำหนดไว้ว่า ตราครุฑ เป็นผลงานอันไม่มีลิขสิทธิ์ เนื่องจากเป็นส่วนประกอบของ ระเบียบ ข้อบังคับ คำสั่ง ฯลฯ ของราชการ แต่ถ้าผมทราบว่าใครเป็นผู้สร้างรูปนี้ขึ้นมาก็คงจะดีกว่านี้
  4. ในระบบของผม (ใช้ debain/lenny) อยู่ ไม่สามารถใช้ latex กับ UTF8 ได้ ดังนั้นแฟ้มทั้งหมดที่สร้างขึ้นนี้ จึงเป็น TIS-620 ทั้งหมด แต่สำหรับท่านที่ต้องการนำไปใช้ หากคัดลอกจากเว็บ ก็สามารถใช้ UTF8 ได้ทันทีโดยเติม \usepackage[utf8]{inputenc} ไว้ที่ส่วน preemble ของเอกสาร ก็น่าจะได้
  5. ในระบบของผม ไม่สามารถใช้คำสั่ง \includegraphics กับ GIF ต้นฉบับได้ (ยังหาสาเหตุไม่ได้) จึงต้องแปลง GIF เป็น EPS แทน ซึ่งการทำเช่นนี้มีจุดอ่อนคือ อาจใช้กับ pdflatex ซึ่งเป็นเครื่องมือหลักของ latex ในวินโดว์ ไม่ได้
  6. คนบางคนในหน่วยราชการบางหน่วย อาจไม่เข้าใจเรื่องแบบอักษร ทำให้ยึดติดอยู่กับแบบอักษรตระกูล Angsana หรือ Browallia หรืออื่น ๆ อันเป็นผลงานที่มีลิขสิทธิ์และมีราคา ไม่มีใช้ในระบบโอเพนซอร์ส และไม่ยอมรับแบบอักษรที่ทางรัฐบาลเป็นผู้สนับสนุนให้สร้างเอง เช่น กินรี นรสีห์ และอื่น ๆ ถ้าเป็นเช่นนี้ก็ช่วยไม่ได้จริง ๆ คงต้องทำใจอย่างเดียว
หลังจากนี้จะรอรับคำชี้แนะเพื่อแก้ไขและปรับปรุงสัก 1 - 2 สัปดาห์ เมื่อแก้ไขและปรับปรุงแล้วจะนำแฟ้มเอกสารต่าง ๆ มาเผยแพร่ต่อไปครับ