เล่น Canon ของ Pachelbel


29

ตัดตอนข้อความที่ตัดตอนมาต่อไปนี้จาก Canon ของ Pachelbel ใน D เป็นเสียง:

Canon ของ Pachelbel ใน D

กฎระเบียบ

  • รูปแบบ / การเข้ารหัสใด ๆ อาจถูกนำมาใช้ตราบใดที่มีตัวแปลงสัญญาณอยู่ก่อนการสร้างความท้าทายนี้
  • เครื่องมือใด ๆ (อาจเป็นเครื่องมือจริง, การสังเคราะห์ MIDI, ฯลฯ )
  • จังหวะต้องเป็น 65 BPM (ตามที่ระบุไว้ในแผ่นเพลง) - หากคุณไม่สามารถรับ 65 BPM คุณสามารถใช้จังหวะใด ๆ ในช่วง (รวม) ช่วง 64.75 - 65.25
  • แผ่นเพลงอยู่ในระดับเสียงคอนเสิร์ต
  • ต้องใช้การปรับแต่งอารมณ์ที่เท่าเทียมกัน (โดยเฉพาะ 12-ET กับ A4 = 440 Hz)

สำหรับการอ้างอิงนี่คือ Stack Snippet ที่จะเล่นข้อความที่ตัดตอนมา:


ข้อมูลโค้ดนั้นจะแข่งขันได้หรือไม่เมื่อดาวน์โหลดจากที่อื่น
Blue

4
@muddyfish ไม่เพราะการดึงเอาท์พุทจากแหล่งภายนอกนั้นเป็นช่องโหว่มาตรฐาน
Mego

การส่งออกไฟล์ midi แทนที่จะเป็นเสียงเป็นที่ยอมรับหรือไม่
DJMcMayhem

@DJMcMayhem ใช่ไฟล์ MIDI เป็นที่ยอมรับ
Mego

ฉันถือว่าคอร์ดสุดท้ายเท่านั้น (เต็ม) จะต้องเต็ม? ที่มีประสิทธิภาพห้ามภาษาที่ไม่ได้ประสานเสียง / API ของ
ระดับแม่น้ำเซนต์

คำตอบ:


9

JavaScript (ES7), 249 242 241 ไบต์

with(new AudioContext)for(t=i=0;n=parseInt('l43l431db98643o86ogfdbdfdgfdzbdzgigikigfdbzbdv98db9864311480'[i++],36);)with(createOscillator())frequency.value=880*2**(-~-n%20/12),connect(destination),start(t),stop(i>56?t+q*8:t+=n>20?q=6/13:q/2)

ขอขอบคุณ @Neil และ @PatrickRoberts เพื่อการประหยัดไบต์

คำอธิบาย

สัญกรณ์จะถูกบรรจุในสตริงที่ตัวละครแต่ละตัวเป็นโน้ตเดี่ยวเป็นตัวเลขฐาน 36 ค่าที่บันทึกจะถูกกำหนดโดยสูตร(19 - pitch) * time + 1ที่pitchเป็นจำนวน semitones น้อยกว่า A5 และtimeเป็น1สำหรับ semiquaver หรือ20สำหรับเครือ 0ที่สิ้นสุดหยุดforห่วง

จังหวะเป็น65.22bpm แก้ไข: 65bpm ว่าตอนนี้สำหรับ 2 ไบต์

คำอธิบาย / การสาธิตนี้ใช้Math.powแทน**ความเข้ากันได้ของเบราว์เซอร์ นอกจากนี้ยังกำหนดกำไรจาก oscillators เพื่อ.3เพื่อให้คอร์ดสุดท้ายไม่ได้ทำให้มีเลือดออกหูของคุณ (กำไรเริ่มต้นคือ1)

with(new AudioContext)            // use HTML5 audio
  for(                            // iterate through the note pitches and lengths
    t=i=0;                        // t = current time to place the note
    n=parseInt(                   // n = note pitch/length

      // Packed notation string
      'l43l431db98643o86ogfdbdfdgfdzbdzgigikigfdbzbdv98db9864311480'

    [i++],36);
  )
    with(createOscillator())      // create the note oscillator

      // Set the note frequency (using Math.pow for the demo).
      //frequency.value=880*2**(-~-n%20/12),
      frequency.value=880*Math.pow(2,-~-n%20/12),

      // Send the note's sound through the speakers (for the demo, we'll connect it to
      // a gain node so we can reduce the volume).
      //connect(destination),
      connect((g=createGain(),g.gain.value=.3,g.connect(destination),g)),

      start(t),                     // schedule the note to sound
      stop(                         // schedule the end of the note
        i>56?                       // if we are in the final chord
          t+                        //   do not increment the time
            q*8                     //   hard-code the length to a semibreve
        :t+=n>20?q=6/13:q/2         // else update the length based on the note value
      )

คุณสามารถกดปุ่มด้านบนเพื่อทดสอบในเบราว์เซอร์ที่สนับสนุน HTML5 Web Audio API


880*2**(-~-n%20/12)ควรช่วยคุณสองสามไบต์
Neil

@ Neil ขอบคุณ ฉันสงสัยว่าฉันสามารถกำจัดได้-~-เช่นกันโดยการเปลี่ยนรูปแบบการจัดเก็บบันทึกย่อของฉัน ( + 1สูตรในนั้นมีเพียงเพราะฉันต้อง0หยุดforลูปและฉันขี้เกียจเกินกว่าที่จะคิดมากก่อนโพสต์)
user81655

เห็นสิ่งนี้หลังจากที่ฉันโพสต์คำตอบของฉัน lol
Patrick Roberts

คุณสามารถบันทึกไบต์อื่นโดยแทนที่c=new AudioContext;ด้วยwith(new AudioContext)และลบทั้งสองเกิดขึ้นc.ในโปรแกรม
Patrick Roberts

1
@ kamoroso94 ไม่เลขชี้กำลังสามารถเป็นเศษส่วนได้ดังนั้นหากฉันใช้<<มันจะทำให้มันเป็นจำนวนเต็ม
user81655

8

Mathematica, 212 152 139 135 ไบต์

{#~(s=##~SoundNote~41&)~1&/@LetterNumber@"uursuursuikmnprsrrnprrfgikigifgiggkiggfdfdbdfgikggkikkmnikmnprsu",{14,18,21}~s~16}~Sound~18.5

ส่งออกSoundวัตถุที่เล่น Canon ของ Pachelbel ใน D เมื่อกดปุ่ม Play เครื่องดนตรีเป็นเครื่องมือ MIDI # 41 "ไวโอลิน"

เสียง

คลิกฉัน!

คำอธิบาย

LetterNumber@"uursuursuikmnprsrrnprrfgikigifgiggkiggfdfdbdfgikggkikkmnikmnprsu"

ค้นหาตัวเลขตัวอักษรของตัวละครแต่ละตัวในสตริง ( "เป็น" -> 1 "B" -> 2 และอื่น ๆ ) Listห่อด้วย (สตริงนี้แสดงถึง Canon ของ Pachelbel ใน D)

#~(s=##~SoundNote~41&)~1&/@...

ตั้งsเป็นSoundNoteฟังก์ชั่นซึ่งเครื่องดนตรีคือ # 41 ตั้งค่าระยะเวลาเป็น 1 และแมปที่ฟังก์ชั่นแต่ละองค์ประกอบในList(ทำให้SoundNoteวัตถุดั้งเดิม)

{14,18,21}~s~16

ทำสามคนสุดท้าย (ระยะเวลา16ในการทำบันทึกครั้งสุดท้ายนานขึ้น 16 เท่า - โน้ตทั้งหมดสิบหกเท่าบันทึกที่สิบหก)

... ~Sound~18.5

ทำให้Soundวัตถุ18.5ยาวเป็นวินาที (เนื่องจากความเร็วคือ 65 bpm [5 การวัด 4/4 ด้วยความเร็ว 65 bpm = ประมาณ 18.5 วินาที])

เวอร์ชัน 126 ไบต์ไม่ใช่การแข่งขัน

Sound[{(s=SoundNote)/@LetterNumber@"uursuursuikmnprsrrnprrfgikigifgiggkiggfdfdbdfgikggkikkmnikmnprsu",{14,18,21}~s~16},240/13]

ไม่แข่งขันเนื่องจากเอาต์พุตมีโน้ตที่สิบสองสองตัวแทนที่จะเป็นโน้ตที่แปดและแยกได้ค่อนข้างชัดเจน


14
จริงๆแล้ว Mathematica ไม่ได้มี Canon ในตัวของ Pachelbel อยู่ในตัว?
Stewie Griffin

1
@StewieGriffin มีเพียงสิ่งเดียวทั้งหมดที่อาจเป็นไปได้และค่าใช้จ่ายในการตัดมันจะสูงเกินไป
Mego

@StewieGriffin น่าแปลกที่มันไม่ได้
JungHwan Min Min

6

หมากฝรั่ง , 203 ไบต์

00000000: e002 2800 c35d 0026 9509 6f34 76f2 ffad  ..(..].&..o4v...
00000010: 4150 0893 a735 bd02 a1eb 1237 18fe 5498  AP...5.....7..T.
00000020: 120a 83e1 6662 8a5e 9709 fe8a 3430 0f48  ....fb.^....40.H
00000030: 5008 54af d19a b44f 2be9 fb3b bf9d 206d  P.T....O+..;.. m
00000040: abbf 12f0 2151 6dae 4712 8c18 4d8e f5cd  ....!Qm.G...M...
00000050: eb85 404c 17cd bd5c 2775 38bd eb50 ab88  ..@L...\'u8..P..
00000060: e015 fb7e 4b1e 5ddb 515b 144c fc5e c1be  ...~K.].Q[.L.^..
00000070: 3d5d 20cd e950 4a1d 256e b56e d364 188b  =] ..PJ.%n.n.d..
00000080: 6fa1 afcc 2100 0235 ada0 2f23 411d 95dd  o...!..5../#A...
00000090: 6665 3b45 041d cbe2 8e3b 2456 fb8d 4e4c  fe;E.....;$V..NL
000000a0: 1a7f b814 a6cf 850e 9b6c 9285 3a6f 1ec3  .........l..:o..
000000b0: 02ed 505c 996b eb4d 209c 2776 a8aa 8380  ..P\.k.M .'v....
000000c0: 42cc b779 218e e75e 8000 00              B..y!..^...

ลองออนไลน์!

นี่คือ hexdump (ย้อนกลับด้วยxxd -r) ของซอร์สโค้ด ไฟล์ MIDI ที่สร้างขึ้นมีดังต่อไปนี้ (เช่น hexdump):

00000000: 4d54 6864 0000 0006 0001 0002 01e0 4d54  MThd..........MT
00000010: 726b 0000 0019 00ff 5902 0200 00ff 5804  rk......Y.....X.
00000020: 0402 1808 00ff 5103 0e15 c500 ff2f 004d  ......Q....../.M
00000030: 5472 6b00 0001 f200 c000 00ff 0405 5069  Trk...........Pi
00000040: 616e 6f00 9051 5f81 5880 5100 1890 4e5f  ano..Q_.X.Q...N_
00000050: 6c80 4e00 0c90 4f5f 6c80 4f00 0c90 515f  l.N...O_l.O...Q_
00000060: 8158 8051 0018 904e 5f6c 804e 000c 904f  .X.Q...N_l.N...O
00000070: 5f6c 804f 000c 9051 5f6c 8051 000c 9045  _l.O...Q_l.Q...E
00000080: 5f6c 8045 000c 9047 5f6c 8047 000c 9049  _l.E...G_l.G...I
00000090: 5f6c 8049 000c 904a 5f6c 804a 000c 904c  _l.I...J_l.J...L
000000a0: 5f6c 804c 000c 904e 5f6c 804e 000c 904f  _l.L...N_l.N...O
000000b0: 5f6c 804f 000c 904e 5f81 5880 4e00 1890  _l.O...N_.X.N...
000000c0: 4a5f 6c80 4a00 0c90 4c5f 6c80 4c00 0c90  J_l.J...L_l.L...
000000d0: 4e5f 8158 804e 0018 9042 5f6c 8042 000c  N_.X.N...B_l.B..
000000e0: 9043 5f6c 8043 000c 9045 5f6c 8045 000c  .C_l.C...E_l.E..
000000f0: 9047 5f6c 8047 000c 9045 5f6c 8045 000c  .G_l.G...E_l.E..
00000100: 9043 5f6c 8043 000c 9045 5f6c 8045 000c  .C_l.C...E_l.E..
00000110: 9042 5f6c 8042 000c 9043 5f6c 8043 000c  .B_l.B...C_l.C..
00000120: 9045 5f6c 8045 000c 9043 5f81 5880 4300  .E_l.E...C_.X.C.
00000130: 1890 475f 6c80 4700 0c90 455f 6c80 4500  ..G_l.G...E_l.E.
00000140: 0c90 435f 8158 8043 0018 9042 5f6c 8042  ..C_.X.C...B_l.B
00000150: 000c 9040 5f6c 8040 000c 9042 5f6c 8042  ...@_l.@...B_l.B
00000160: 000c 9040 5f6c 8040 000c 903e 5f6c 803e  ...@_l.@...>_l.>
00000170: 000c 9040 5f6c 8040 000c 9042 5f6c 8042  ...@_l.@...B_l.B
00000180: 000c 9043 5f6c 8043 000c 9045 5f6c 8045  ...C_l.C...E_l.E
00000190: 000c 9047 5f6c 8047 000c 9043 5f81 5880  ...G_l.G...C_.X.
000001a0: 4300 1890 475f 6c80 4700 0c90 455f 6c80  C...G_l.G...E_l.
000001b0: 4500 0c90 475f 8158 8047 0018 9049 5f6c  E...G_.X.G...I_l
000001c0: 8049 000c 904a 5f6c 804a 000c 9045 5f6c  .I...J_l.J...E_l
000001d0: 8045 000c 9047 5f6c 8047 000c 9049 5f6c  .E...G_l.G...I_l
000001e0: 8049 000c 904a 5f6c 804a 000c 904c 5f6c  .I...J_l.J...L_l
000001f0: 804c 000c 904e 5f6c 804e 000c 904f 5f6c  .L...N_l.N...O_l
00000200: 804f 000c 9051 5f6c 8051 000c 904a 5f00  .O...Q_l.Q...J_.
00000210: 904e 5f00 9051 5f8e 4c80 4a00 0080 4e00  .N_..Q_.L.J...N.
00000220: 0080 5100 8360 ff2f 00                   ..Q..`./.

6

BBC BASIC, 141 ASCII ตัวละคร (65.217BPM)

*TEMPO1
F.i=2TO71j=i>65SOUND1-j*(479+i/2),-9,ASCM." \\VX\\VX\DHLNRVXVVNRVV>@DHD@D>@D@@HD@@>:>:6:>@DH@@HDHHLNLDHLNRVXNNVV\\",i)*2,23-j*161N.

แก้ไขเพื่อรองรับขีด จำกัด ของความเร็ว จะอัปเดตคำอธิบายในภายหลัง

BBC BASIC, 123 อักขระ ASCII (ไม่ใช่การแข่งขันที่ 60BPM)

ดาวน์โหลดล่ามได้ที่ http://www.bbcbasic.co.uk/bbcwin/download.html

เล่นเพลงโดยตรงเมื่อเรียกใช้

F.i=1TO67j=i>64SOUND1-j*(447+i),-9,ASCM."\\VX\\VX\DHLNRVXVVNRVV>@DHD@D>@D@@HD@@>:>:6:>@DH@@HDHHLNLDHLNRVXNV\",i)*2,5-j*75N.

Ungolfed

  FOR i = 1 TO 67
    j = i > 64: REM j=0 for the first four bars composed of 16th notes, j=-1 for the final chord (whole note)
    SOUND 1 - j * (447 + i), -9, ASC(MID$("\\VX\\VX\DHLNRVXVVNRVV>@DHD@D>@D@@HD@@>:>:6:>@DH@@HDHHLNLDHLNRVXNV\", i)) * 2, 5 - j * 75
  NEXT i

คำอธิบาย

jเป็นธงที่ระบุว่าเราอยู่ใน 4 แท่งแรกหรือคอร์ดสุดท้าย TRUE คือ-1ใน BBC BASIC

SOUNDคำสั่งใช้เวลา 4 พารามิเตอร์:

ช่อง: สำหรับ 4 แท่งแรกนี่คือช่อง 1 สำหรับ 3 โน้ตของคอร์ดในแถบที่ 5 หมายเลขช่องคือ 201, 202 และ 203 ฐานสิบหก (513,514 และทศนิยม 515) หมายความว่าเล่นบนช่อง 1,2 และ 3 เริ่มต้น 2 ความหมายเล่นพร้อมกันกับ 2 บันทึกในช่องทางอื่น ๆ (เช่นเล่นคอร์ด 3 หมายเหตุ)

VOLUME: กำหนดให้เป็นค่าลบเนื่องจากค่าบวกหมายถึงเอฟเฟกต์อื่น ๆ (ซองเสียง) ตั้งที่ -9 (ขึ้นไปที่ -15 ซึ่งดังที่สุด)

PITCH: สำหรับเพลงนี้ช่วงจาก D4 = 108 ถึง A5 = 184 แต่ละขั้นตอนเป็นจำนวนเต็ม 1/4 ของ semitone ค่าจะถูกจัดเก็บเป็นรหัส ASCII ในช่วง 54 ถึง 92 และเพิ่มเป็นสองเท่าเพื่อสร้างค่าที่ถูกต้องใหม่ 1 / 8th บันทึกจะถูกเก็บไว้เป็นบันทึก 1/16 ที่ซ้ำกัน คอร์ดสุดท้ายจะถูกจัดเก็บเป็น 3 ระดับแยกกันและความยาวโน้ตแตกต่างกันไปตามโน้ตทั้งหมดดังนี้

ระยะเวลา: ใน 1/20 ของวินาที ระยะเวลาของบันทึก 1 / 16th คือ 5/20 ของวินาทีดังนั้น 60 บันทึก 1/4 ต่อนาที (มีความละเอียดไม่เพียงพอที่จะทำให้จังหวะที่แม่นยำมากขึ้น) บันทึกทั้งหมดคือ 5 - (- 75) = 80 หน่วย (4 วินาที ) ยาว


สิ่งนี้ไม่ควรระบุว่าไม่ใช่การแข่งขันใช่ไหม
JungHwan Min Min

@JungHwanMin เพื่อตอบข้อความต้นฉบับของความคิดเห็นของคุณ: BPM อยู่ภายใน 10% จาก 65 ไม่มีความแม่นยำในคำถาม การโทรของ OP
เลเวลริเวอร์เซนต์

60 bpm นั้นแตกต่างจากการได้ยิน 65 bpm ฉันจะอนุญาตให้สิ่งนี้ไม่ใช่การแข่งขันเนื่องจากเป็นข้อ จำกัด ที่กำหนดโดยภาษา
Mego

@ ก่อนหน้านี้ฉันคิดว่า BBC Basic นับเป็นครั้งที่ 100 ในวินาทีโดยค่าเริ่มต้นฉันไม่ได้ตระหนักว่ามันหยาบเท่าที่ 20 วินาที ฉันปรับรหัสของฉันเป็น 100 แล้วดังนั้นตอนนี้ฉันสามารถทำ 65.215BPM ได้ไหม ใช้เวลาเล่นซอเล็ก ๆ น้อย ๆ เป็นพิเศษเนื่องจากโน้ตทั้งหมดเกิน 256/100 ดังนั้นฉันจึงต้องเล่นมันเป็นโน้ตสองครึ่ง 50th ของวินาทีจะเป็นรหัสที่สั้นกว่า แต่ 62.5BPM นั้นไม่ได้รับการปรับปรุงมากนัก
ระดับแม่น้ำเซนต์

โดยวิธีการมีข้อผิดพลาดการถอดความเล็กน้อยในโพสต์เดิม คุณอาจต้องเปลี่ยนรหัสเล็กน้อย (รหัสปัจจุบันมีรุ่นที่ไม่ถูกต้อง)
JungHwan Min

4

Befunge ขนาด 242 ไบต์

การปรับแต่งนั้นเขียนไปยัง stdout ในรูปแบบของไฟล์ MIDI คุณจะต้องเปลี่ยนเส้นทางเอาต์พุตไปยังไฟล์. midเพื่อเล่นข้อความที่ตัดตอนมา

<v:"MThd"0006000101"MTrk"001+"~e"0*3"UQ"30*5"-\"9
v>9#:-#,_0"QONLJIGEJIGEGCGECB@>@B@BCEGCECBECEGECBNLJNONLJIGEQONQONQ"0\:
_v#:\%+77+1,"@",\,*8*82,+3*4!*-3::\,"@",:,*:*62,1
v>"QNJQNJ"0\:
_v#:\+1,"@",\,-**82/3\*:*62:,+!\**97!-3::\
@>,\"/U"3*,,,

ลองออนไลน์! แม้ว่าฉันไม่คิดว่ามันเป็นไปได้ในขณะนี้เพื่อบันทึกผลลัพธ์ในลักษณะที่มันจะรักษาความสมบูรณ์ของข้อมูลไบนารี

คำอธิบาย

บรรทัดแรกมีความสำคัญเพียงส่วนหัวของ MIDI ที่เขียนโค้ดอย่างหนักซึ่งเป็นเอาต์พุตเมื่อเริ่มต้นบรรทัดที่สอง ส่วนที่เหลือของบรรทัดที่สองเข้ารหัสลำดับของบันทึกย่อเป็นค่า MIDI ซึ่งเป็น ASCII ที่สะดวก บรรทัดที่สามเขียนคำสั่ง MIDI สำหรับเล่นโน้ตเหล่านั้นโดยมีการคำนวณระยะเวลาโดยอัตโนมัติ (โน้ตทุกอันเป็นเซมิเซวิเวอร์เว้นแต่ว่า i% 14 == 0) คอร์ดสุดท้ายได้รับการจัดการเป็นกรณีพิเศษบนบรรทัดที่สี่และห้า (เนื่องจากต้องกดหลายคีย์พร้อมกัน) และบรรทัดที่หกเขียน MIDI สุดท้ายของแทร็กเครื่องหมายสุดท้าย


4

C, 248 228 210 198 193 191 ไบต์

#define y(x)cos(.346*t*exp(x/17.))
d=1846,t;main(c){for(;t++<d*80;putchar(c=((t<d*64?y(("TTQRTTQRTHJLMOQRQQMOQQEFHJHFHEFHFFJHFFECECACEFHJFFJHJJLMHJLMOQRT"[t/d]-72)):y(12)+y(9)+y(5))+3)*42));}

สิ่งนี้จะสร้างลำดับของตัวอย่างที่ไม่ได้ลงชื่อ 8 บิตที่ต้องการเล่นที่ 8000 ตัวอย่างต่อวินาที หากคุณมีการติดตั้งเก่า Unix / Linux /dev/audioคุณสามารถเปลี่ยนเส้นทางออกไป ใน Linux distros ที่ใหม่กว่าคุณอาจจะต้องไพพ์เอาต์พุตไปยัง ALSA command line playeraplay


อย่างดีเลิศ. สุดยอดทางออก!
Abel Tom

1

SmileBASIC ขนาด 115 ไบต์

BGMPLAY"@305T65L16[A8F+G]2A{r}F#8>F#GABAGAF#GAG8BAG8F#EF#EDEF#GABG8BAB8<C#D{r}AA1:1[R1]4F#1:2[R1]4D1{r=>AB<C#DEF#G}

การใช้เครื่องมือที่ดีมีค่า 4 ไบต์พิเศษ :)


เครื่องดนตรี 305 คืออะไร
Pavel

SmileBASIC มีเครื่องมือ MIDI ทั่วไปทั้งหมด แต่ก็มีเครื่องมือที่ไม่มีเอกสาร "ความลับ" นี่คือตัวอย่างของ Canon รุ่นที่ซับซ้อนกว่าของ Pachelbel ที่เล่นโดยใช้เครื่องมือนั้น: dropbox.com/s/wfhr90tdkkji6qy/305.mp3?dl=0
12Me21

0

JavaScript (ES6) โดยใช้WAV.jsขนาด 325 ไบต์

w=new WAV();w.addProgression(btoa9‘¹9‘¹8€¹‘9‘¹‘y‘9‘y¸€x¸x€8¸€8¸888¸€x¸€8€xù€xù‘y9`.replace(/[CF]./g,'$&#').split(/(?=[A-G])/g).map((f=t=>n=>({note:n,time:t}))(15/65)));['D5','F5#','A5'].map(n=>w.addNote(f(48/13)(n),.3,[],1,1));new Audio(URL.createObjectURL(w.toBlob())).play()
<script src="https://cdn.rawgit.com/patrickroberts/3b065ab94ce5094baacf45ed23e2a16e/raw/9c367e292fbee8341e1019d0d5953a2234449882/wav.babel.js"></script>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.