| Octave | Note Numbers | |||||||||||
| C | C# | D | D# | E | F | F# | G | G# | A | A# | B | |
| -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 0 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
| 2 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
| 3 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
| 4 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
| 5 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
| 6 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
| 7 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
| 8 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |
| 9 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | ||||
เรามาเริ่มทำอะไรที่ดูเกี่ยวกับดนตรีมากขึ้นกันดีกว่า หลังจากที่ผ่านมา เจอเน่านี้ นำเสนอด้านการเขียนโปรแกรมมาหลายทีละ อิอิ
(แต่สิ่งที่จะทำให้ดูต่อไปนี่ ก็อาศัยผสมผสานประสบการณ์ที่ผ่านๆมาใน เจอเน่านะครับ
ถ้าใครอ่านแล้วงง อาจจะเป็นเพราะว่า ยังไม่ได้ลองทำอันที่ผ่านๆมาเล่น)
แล้วนี่เอาตารางอะไรของชาวบ้านเขาขึ้นมาเนี่ย
จะดูดวงกันหรือไง? อ้อ ไม่ใช่
นี่คือ ตาราง MIDI Note Numbers!
http://www.harmony-central.com/MIDI/Doc/table2.html
จากระบบการส่งข้อมูลของ midi
ก็ได้เกิดมาตรฐานที่เป็นที่นิยมกัน
ในการส่งค่าระดับเสียง โน้ต ในดนตรีสากล
ระดับเสียงที่ว่านี้ ก็เทียบตามโน้ตในดนตรีสากลโดยตรงเลย
ก็คือ โด่ เร มี้ ฯลฯ
โดยไล่ ออคเทฟ (octave) ต่างๆ
ตั้งแต่ ต่ำกว่าเปียโน จนไปถึงสูงกว่าเปียโน
ด้วยความที่ ยุคนั้น ค่าของ midi ยังรับส่งกันด้วยข้อมูล 7 bit แบบนี้
(สมัยนี้ก็เห็นยังใช้อยู่นะ ฮ่าๆๆ)
ทำให้ ส่งความละเอียดได้เพียง 27 นั่นคือ 128 หน่วย
ถ้าคิดเป็นโน้ต ก็คือ มันครอบคลุมจำนวนโน้ตที่กว้างมาก
กว้างกว่าเปียโนหน่อยๆ ก็ถือว่า ใช้ทำงานดนตรีได้กว้างพอควรเลยล่ะ
สิ่งที่ควรรู้ก็คือ:
ระบบดนตรีสากลดั้งเดิมเนี่ย
จะแบ่งระดับเสียงต่างๆ เป็น octaveๆ
เวลาลองไล่โน้ตครบชุดหนึ่ง
เมื่อโน้ตไล่แล้ววนกลับมาเป็นโน้ตตัวเดิม
(แต่มีระดับเสียงต่างกัน)
ก็จะเรียกว่า เป็นโน้ตเดียวกันแต่อยู่ต่าง octave กัน
เช่น โด่ โด โด๊
-_-"
คราวนี้ มีตัว โด (C) ตัวหนึ่ง เป็น C ที่มีจุดเด่นอยู่ตรงที่
เป็นโน้ตที่เป็นเสียงที่อยู่ตรงกลางระหว่างเสียงผู้ชายกับผู้หญิง
(แล้วก็เป็น C ที่อยู่ กลางๆ ค่อนไปทางซ้ายนิดๆ ของ piano)
โน้ตตัวนี้ เรียกว่า middle C (C กลาง)
ในระบบ midi ก็ได้กำหนดว่า โน้ตหมายเลข 60 นั้น ให้เป็น C กลาง
หลังจากนั้น โน้ตอื่นๆ ก็จะคิดเทียบกับ ซี กลาง ได้เลย
คราวนี้ อีกหนึ่งอย่างที่ควรรู้จักก็คือ tone และ semitone
โทน ก็คือโทนเสียง และการเทียบเสียง ตามปกติที่เรารู้จัก
เช่น ถ้าเราเคยออกเสียงร้อง โด เร มี ฟา ..
การเดินทางจาก โด ไป เร.. นี่ก็คือ เพิ่มขึ้น 1 โทนเสียง
เร ไป มี ก็เพิ่มขึ้น 2 โทนเสียง..
เป็นเช่นนี้ไปเรื่อยๆ
แต่ถ้า ลองคิดเสียงในหัวดู (โดยเฉพาะคนที่รู้จัก major scale)
จะสังเกตได้ว่า เสียงที่เพิ่มขึ้นไป ในแต่ละโทนเสียง มันไม่ได้ขึ้นไปเท่ากัน
บางที มันก็เหมือนขึ้นไป 1 โทนเต็มๆ
บางที ก็เหมือนเดินขึ้นไปแค่ ครึ่งโทนเสียงเท่านั้น
เช่น โด ไปเร นี่ เพิ่ม 1 โทนเสียง
แต่ลองออกเสียง มี ไปฟา นี่รู้สึกได้ว่า เพิ่มขึ้นไปแค่ ครึ่งเท่านั้น)
ศัพท์ที่ว่า "ครึ่งโทนเสียง" ก็เรียกว่า semitone (เซมิโทน .. เซมิ = ครึ่ง)
ในดนตรีสากลปกติที่เรารู้จัก ระดับเสียงที่ห่างกัน 1 octave นั้น
ห่างกัน 12 semitone ด้วยกัน
ดูจากตารางแล้วก็จะเห็นสอดคล่้องกัน ก็คือ
เมื่อโน้ตขึ้น octave ใหม่ ก็จะวนทีละ 12 ตัว
(แต่สิ่งที่จะทำให้ดูต่อไปนี่ ก็อาศัยผสมผสานประสบการณ์ที่ผ่านๆมาใน เจอเน่านะครับ
ถ้าใครอ่านแล้วงง อาจจะเป็นเพราะว่า ยังไม่ได้ลองทำอันที่ผ่านๆมาเล่น)
แล้วนี่เอาตารางอะไรของชาวบ้านเขาขึ้นมาเนี่ย
จะดูดวงกันหรือไง? อ้อ ไม่ใช่
นี่คือ ตาราง MIDI Note Numbers!
http://www.harmony-central.com/MIDI/Doc/table2.html
จากระบบการส่งข้อมูลของ midi
ก็ได้เกิดมาตรฐานที่เป็นที่นิยมกัน
ในการส่งค่าระดับเสียง โน้ต ในดนตรีสากล
ระดับเสียงที่ว่านี้ ก็เทียบตามโน้ตในดนตรีสากลโดยตรงเลย
ก็คือ โด่ เร มี้ ฯลฯ
โดยไล่ ออคเทฟ (octave) ต่างๆ
ตั้งแต่ ต่ำกว่าเปียโน จนไปถึงสูงกว่าเปียโน
ด้วยความที่ ยุคนั้น ค่าของ midi ยังรับส่งกันด้วยข้อมูล 7 bit แบบนี้
(สมัยนี้ก็เห็นยังใช้อยู่นะ ฮ่าๆๆ)
ทำให้ ส่งความละเอียดได้เพียง 27 นั่นคือ 128 หน่วย
ถ้าคิดเป็นโน้ต ก็คือ มันครอบคลุมจำนวนโน้ตที่กว้างมาก
กว้างกว่าเปียโนหน่อยๆ ก็ถือว่า ใช้ทำงานดนตรีได้กว้างพอควรเลยล่ะ
สิ่งที่ควรรู้ก็คือ:
ระบบดนตรีสากลดั้งเดิมเนี่ย
จะแบ่งระดับเสียงต่างๆ เป็น octaveๆ
เวลาลองไล่โน้ตครบชุดหนึ่ง
เมื่อโน้ตไล่แล้ววนกลับมาเป็นโน้ตตัวเดิม
(แต่มีระดับเสียงต่างกัน)
ก็จะเรียกว่า เป็นโน้ตเดียวกันแต่อยู่ต่าง octave กัน
เช่น โด่ โด โด๊
-_-"
คราวนี้ มีตัว โด (C) ตัวหนึ่ง เป็น C ที่มีจุดเด่นอยู่ตรงที่
เป็นโน้ตที่เป็นเสียงที่อยู่ตรงกลางระหว่างเสียงผู้ชายกับผู้หญิง
(แล้วก็เป็น C ที่อยู่ กลางๆ ค่อนไปทางซ้ายนิดๆ ของ piano)
โน้ตตัวนี้ เรียกว่า middle C (C กลาง)
ในระบบ midi ก็ได้กำหนดว่า โน้ตหมายเลข 60 นั้น ให้เป็น C กลาง
หลังจากนั้น โน้ตอื่นๆ ก็จะคิดเทียบกับ ซี กลาง ได้เลย
คราวนี้ อีกหนึ่งอย่างที่ควรรู้จักก็คือ tone และ semitone
โทน ก็คือโทนเสียง และการเทียบเสียง ตามปกติที่เรารู้จัก
เช่น ถ้าเราเคยออกเสียงร้อง โด เร มี ฟา ..
การเดินทางจาก โด ไป เร.. นี่ก็คือ เพิ่มขึ้น 1 โทนเสียง
เร ไป มี ก็เพิ่มขึ้น 2 โทนเสียง..
เป็นเช่นนี้ไปเรื่อยๆ
แต่ถ้า ลองคิดเสียงในหัวดู (โดยเฉพาะคนที่รู้จัก major scale)
จะสังเกตได้ว่า เสียงที่เพิ่มขึ้นไป ในแต่ละโทนเสียง มันไม่ได้ขึ้นไปเท่ากัน
บางที มันก็เหมือนขึ้นไป 1 โทนเต็มๆ
บางที ก็เหมือนเดินขึ้นไปแค่ ครึ่งโทนเสียงเท่านั้น
เช่น โด ไปเร นี่ เพิ่ม 1 โทนเสียง
แต่ลองออกเสียง มี ไปฟา นี่รู้สึกได้ว่า เพิ่มขึ้นไปแค่ ครึ่งเท่านั้น)
ศัพท์ที่ว่า "ครึ่งโทนเสียง" ก็เรียกว่า semitone (เซมิโทน .. เซมิ = ครึ่ง)
ในดนตรีสากลปกติที่เรารู้จัก ระดับเสียงที่ห่างกัน 1 octave นั้น
ห่างกัน 12 semitone ด้วยกัน
ดูจากตารางแล้วก็จะเห็นสอดคล่้องกัน ก็คือ
เมื่อโน้ตขึ้น octave ใหม่ ก็จะวนทีละ 12 ตัว
ตอนนี้เรามาทดลองฟังเสียงกันดีกว่า
เริ่มจาก UGen (unit generator) ที่เรารู้จักแล้วก็คือ
SinOsc.. (sine wave oscillator)
พิมพ์โค้ดดังนี้ครับ
SinOsc s1 => dac;
2::second => now;
เสร็จแล้วลอง Add Shred แล้วฟังดู
อันนี้ก็เป็นการฟังเสียง Sine Wave อย่างง่ายๆ
แต่ว่าจะเห็นว่า เขาปรับความถี่ไว้แล้ว
แต่เป็นเท่าไหร่ล่ะ?
การที่เราจะ อ่าน (read) หรือ ปรับ (write) ค่าความถี่ของ oscillator หนึ่งๆนั้น
มีฟังก์ชั่นหนึ่งๆ ที่ทำงานอย่างนี้ของ oscillator ต่างๆ
ก็คือ freq()
ถ้าเรียก freq() ตรงๆเลย ก็จะเป็นการ อ่านค่า
อ่านแล้วก็นำมาใช้งานต่างๆ (เช่นคำนวณ..) หรือนำมาพิมพ์ออกจอก็ได้ เช่น
SinOsc s1 => dac;
<<< s1.freq() >>>;
2::second => now;
จะเห็นว่า เขาพิมพ์ค่าออกมาทาง Console ว่า 220.0 เป็นค่าชนิด float
ก็แปลว่า ความถี่ของ s1 ในขณะนั้น เป็น 220hz
ถ้าใครคุ้นๆ อาจจะเคยได้ยินกว่า A 440hz
โน้ต A ที่เป็นโน้ตที่ชอบใช้จูนเครื่องดนตรีคลาสสิค ทั่วไป
(เช่น.. ไวโอลิน สายเปล่า สาย 2..)
แล้ว 220hz นี่มันโน้ตอะไรกัน
อ๋อ มันมีค่าเพียงแค่ ครึ่งเดียวของ A 440hz
งั้นมันก็คือ A 220hz พอดี..
โน้ตที่มีความถี่ครึ่งเดียว ก็คือโน้ตเดียวกัน ที่ต่ำลงมา 1 octave
ในทางกลับกัน
โน้ตที่มีความถี่เป็นสองเท่า ก็คือโน้ตเดียวกัน ที่สูงขึ้นไป 1 octave
(ก็แปลว่า ถ้าจะหา A ที่สูงกว่า A 440hz ไป 1 octave ก็จะมีความถี่ 440x2 = 880hz)
คราวนี้ ลองหันไปดูตารางข้างบนกัน
เราจะเห็นว่า C กลาง.. มีค่า midi note number = 60
ถ้ามองแถวๆนั้น จะเห็น A ที่สูงกว่า C กลาง และต่ำกว่า C กลาง
ก็คือมีค่า 69 และ 57 ตามลำดับ
ลองพิมพ์โค้ดตามนี้เลย
SinOsc s1 => dac;
57 => int noteNumber;
s1.freq(Std.mtof(noteNumber));
1::second => now;
69 => noteNumber;
s1.freq(Std.mtof(noteNumber));
1::second => now;
ลองทำแล้วฟังเสียงดูครับ
แล้วลองทำแบบนี้
ทำการพิมพ์ค่าของ s1.freq() ออกมา ในช่วงบรรทัดต่างๆ
จะเห็นว่า ข้างบนนี่ เราได้ทำการเปลี่ยน ความถี่ของ s1 ให้กลายเป็นค่าใหม่
แต่ค่าใหม่นี้ เราใช้ ฟังก์ชั่นหนึ่ง คือ Std.mtof()
ในภาษา ชัก มีฟังก์ชั่นมาตรฐานในการทำงานต่างๆมากมาย
ซึ่งอยู่ใน Std นี่แหละ (standard)
อย่างเช่น Std.mtof คู่มืออธิบายดังนี้
[function]: float mtof ( float value );
- converts a MIDI note number to frequency (Hz)
- note the input value is of type 'float' (supports fractional note number)
mtof สามารถรับค่าเป็น float ได้ด้วย
(รับค่า midi note ที่ไม่เป็นจำนวนเต็มได้ เช่นเราอยากรู้ความถี่ของ โน้ตที่
อยู่กึ่งๆระหว่าง C และ C# ก็ยังได้)
ที่เขาเขียนว่า float mtof ( float value)
และ float ตัวหลัง หมายถึง มันจะรับค่าที่จะนำไปคำนวณชนิด float
ลองแบบนี้กันเลยก็ได้
<<< Std.mtof(57) >>>;
จะเห็นว่า ที่ Console แสดงค่าความถี่ของ A ตัวที่ต่ำว่า C กลางขึ้นมาทันที
ก็คือ ความถี่ 220hz แต่แสดงเป็น 220.0 (เป็นค่าชนิด float)
ให้ลองทำ:
ลองใช้ Std.mtof()
ในการปรับ SinOsc ให้เป็นโน้ตตามตาราง
แล้วอาศัยการ ชัก เวลา (เช่น 0.5::second, 1::second ฯลฯ) ใส่ now
ในการปรับความยาวของโน้ตต่างๆ
แล้วทำออกมาเป็นเพลงฮะ
ตัวอย่าง:
SinOsc s1 => dac;
Std.mtof(64) => s1.freq; second => now;
Std.mtof(60) => s1.freq; second => now;
Std.mtof(62) => s1.freq; second => now;
Std.mtof(55) => s1.freq; 1.5::second => now;
s1.gain(0.0); .5::second => now;
s1.gain(1.0);
Std.mtof(55) => s1.freq; second => now;
Std.mtof(62) => s1.freq; 1.25::second => now;
Std.mtof(64) => s1.freq; 1.5::second => now;
Std.mtof(64) => s1.freq; 2::second => now;
s1.gain(0.0); .5::second => now;
s1.gain(1.0);
Std.mtof(48) => s1.freq; 2::second => now;
หมายเหตุ:
การ => ใส่ฟังก์ชั่น มีความหมายเดียวกับการส่งค่านั้นใน function
ดังนั้น การ (สิ่งที่ต้องการ) => s1.freq มีความหมายเท่ากับ s1.freq(สิ่งที่ต้องการ)
gain ก็เป็น function ของ SinOsc เช่นเดียวกับ freq
ตัว freq นั้น เป็นฟังก์ชั่นสำหรับ อ่าน และ ปรับค่า ความถี่
ส่วน gain นั้น อ๋อ ถ้าให้เดาแล้ว ไม่ยากเลย มันก็คือ ความดังน่ะแหละ
0.0 ก็คือ เงียบสนิท, 1.0 ก็คือดัง 100% ดังสุดแล้ว