<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>เอฟเฟกต์เสียง Whammy กีตาร์</title>
    <!-- โหลด Tailwind CSS สำหรับการจัดสไตล์ -->
    <script src="https://[Log in to view URL]"></script>
    <style>
        /* กำหนดฟอนต์ Inter สำหรับทั้งหน้า */
        body {
            font-family: 'Inter', sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #1a202c; /* สีพื้นหลังเข้ม */
            color: #e2e8f0; /* สีข้อความอ่อน */
            padding: 1rem; /* เพิ่ม padding สำหรับหน้าจอขนาดเล็ก */
        }
        /* จัดสไตล์คอนเทนเนอร์หลัก */
        .container {
            background-color: #2d3748; /* สีพื้นหลังคอนเทนเนอร์ที่อ่อนลงเล็กน้อย */
            padding: 2.5rem;
            border-radius: 1rem; /* มุมโค้งมน */
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2); /* เงา */
            max-width: 90%; /* ความกว้างสูงสุด */
            width: 400px; /* ความกว้างที่กำหนด */
            text-align: center;
        }
        /* จัดสไตล์แถบเลื่อน (range input) */
        input[type="range"] {
            -webkit-appearance: none; /* ลบสไตล์เริ่มต้นของเบราว์เซอร์ */
            width: 100%;
            height: 8px;
            background: #4a5568; /* สีพื้นหลังของแถบเลื่อน */
            border-radius: 5px;
            outline: none;
            opacity: 0.7;
            transition: opacity .2s; /* เพิ่ม transition เมื่อ hover */
        }
        input[type="range"]:hover {
            opacity: 1;
        }
        /* จัดสไตล์ปุ่มเลื่อน (thumb) ของแถบเลื่อนสำหรับ WebKit (Chrome, Safari) */
        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 24px;
            height: 24px;
            background: #63b3ed; /* สีฟ้าสำหรับปุ่มเลื่อน */
            border-radius: 50%; /* ทำให้เป็นวงกลม */
            cursor: pointer;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
        }
        /* จัดสไตล์ปุ่มเลื่อน (thumb) ของแถบเลื่อนสำหรับ Firefox */
        input[type="range"]::-moz-range-thumb {
            width: 24px;
            height: 24px;
            background: #63b3ed;
            border-radius: 50%;
            cursor: pointer;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
        }
        /* เพิ่ม transition ให้กับปุ่ม */
        button {
            transition: background-color 0.3s ease, transform 0.1s ease;
        }
        button:hover {
            transform: translateY(-2px); /* ยกปุ่มขึ้นเล็กน้อยเมื่อ hover */
        }
        button:active {
            transform: translateY(0); /* กลับสู่ตำแหน่งเดิมเมื่อคลิก */
        }
    </style>
</head>
<body>
    <div class="container">
        <h1 class="text-3xl font-bold mb-6 text-blue-300">เอฟเฟกต์เสียง Whammy กีตาร์</h1>
        <p class="mb-6 text-gray-300">
            ใช้แถบเลื่อนเพื่อปรับระดับเสียงและสร้างเอฟเฟกต์ Whammy!
        </p>

        <div class="mb-8">
            <button id="playButton" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-lg shadow-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-75">
                เล่นเสียง
            </button>
            <button id="stopButton" class="bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-6 rounded-lg shadow-lg ml-4 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-75" disabled>
                หยุดเสียง
            </button>
        </div>

        <div class="mb-6">
            <label for="whammyRange" class="block text-lg font-medium mb-2 text-gray-200">Whammy Pitch:</label>
            <input type="range" id="whammyRange" min="-1200" max="1200" value="0" class="w-full">
            <div id="pitchValue" class="mt-2 text-sm text-gray-400">0.00 เซมิโทน</div>
        </div>

        <p class="text-sm text-gray-500 mt-8">
            สร้างโดย Web Audio API
        </p>
    </div>

    <script>
        let audioContext; // ตัวแปรสำหรับ AudioContext
        let oscillator;    // ตัวแปรสำหรับ OscillatorNode (สร้างเสียง)
        let gainNode;      // ตัวแปรสำหรับ GainNode (ควบคุมระดับเสียง)
        let isPlaying = false; // สถานะการเล่นเสียง

        const baseFrequency = 440; // ความถี่เริ่มต้น (A4 note)

        /**
         * ฟังก์ชันสำหรับเริ่มต้น AudioContext และ Audio Nodes
         * จะถูกเรียกเมื่อผู้ใช้คลิกปุ่ม "เล่นเสียง" ครั้งแรก
         */
        function initAudio() {
            // ตรวจสอบว่า AudioContext ยังไม่ได้ถูกสร้าง
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }

            // สร้าง OscillatorNode เพื่อสร้างคลื่นเสียง
            oscillator = audioContext.createOscillator();
            oscillator.type = 'sine'; // กำหนดชนิดคลื่นเป็น Sine wave เพื่อเสียงที่สะอาด
            // กำหนดความถี่เริ่มต้นของ Oscillator
            oscillator.frequency.setValueAtTime(baseFrequency, audioContext.currentTime);

            // สร้าง GainNode เพื่อควบคุมระดับเสียง (Volume)
            gainNode = audioContext.createGain();
            // กำหนดระดับเสียงเริ่มต้น
            gainNode.gain.setValueAtTime(0.5, audioContext.currentTime);

            // เชื่อมต่อ Audio Nodes เข้าด้วยกัน: Oscillator -> Gain -> ลำโพง (destination)
            oscillator.connect(gainNode);
            gainNode.connect(audioContext.destination);
        }

        /**
         * ฟังก์ชันสำหรับเริ่มเล่นเสียง
         */
        function playSound() {
            if (isPlaying) return; // ถ้ากำลังเล่นอยู่แล้ว ไม่ต้องทำอะไร

            initAudio(); // เริ่มต้น AudioContext และ Nodes หากยังไม่ได้ทำ
            oscillator.start(); // เริ่มต้น Oscillator เพื่อให้เสียงเล่น
            isPlaying = true; // ตั้งสถานะว่ากำลังเล่น

            // อัปเดตสถานะปุ่ม
            document.getElementById('playButton').disabled = true;
            document.getElementById('stopButton').disabled = false;
        }

        /**
         * ฟังก์ชันสำหรับหยุดเล่นเสียง
         */
        function stopSound() {
            if (!isPlaying) return; // ถ้าไม่ได้เล่นอยู่แล้ว ไม่ต้องทำอะไร

            oscillator.stop(); // หยุด Oscillator
            oscillator.disconnect(); // ตัดการเชื่อมต่อเพื่อช่วยในการจัดการหน่วยความจำ (garbage collection)
            isPlaying = false; // ตั้งสถานะว่าหยุดเล่น

            // อัปเดตสถานะปุ่ม
            document.getElementById('playButton').disabled = false;
            document.getElementById('stopButton').disabled = true;
        }

        /**
         * ฟังก์ชันสำหรับอัปเดตระดับเสียง (Pitch) ตามค่าแถบเลื่อน
         * @param {number} cents - ค่าเป็นเซนต์ (100 เซนต์ = 1 เซมิโทน)
         */
        function updatePitch(cents) {
            if (!oscillator) return; // ถ้า Oscillator ยังไม่ถูกสร้าง ไม่ต้องทำอะไร

            // คำนวณอัตราส่วนความถี่จากค่าเซนต์
            // สูตร: newFrequency = baseFrequency * 2^(cents / 1200)
            // 1200 เซนต์ = 1 อ็อกเทฟ (Octave)
            const frequencyRatio = Math.pow(2, cents / 1200);

            const newFrequency = baseFrequency * frequencyRatio;
            // กำหนดความถี่ใหม่ให้กับ Oscillator อย่างราบรื่น
            oscillator.frequency.setValueAtTime(newFrequency, audioContext.currentTime);

            // อัปเดตค่าที่แสดงบนหน้าจอ (แปลงเป็นเซมิโทน)
            document.getElementById('pitchValue').textContent = `${(cents / 100).toFixed(2)} เซมิโทน`;
        }

        // เพิ่ม Event Listener สำหรับปุ่ม "เล่นเสียง"
        document.getElementById('playButton').addEventListener('click', playSound);
        // เพิ่ม Event Listener สำหรับปุ่ม "หยุดเสียง"
        document.getElementById('stopButton').addEventListener('click', stopSound);

        // เพิ่ม Event Listener สำหรับแถบเลื่อน Whammy Pitch
        const whammyRange = document.getElementById('whammyRange');
        whammyRange.addEventListener('input', (event) => {
            // เรียกฟังก์ชัน updatePitch เมื่อแถบเลื่อนมีการเปลี่ยนแปลง
            updatePitch(parseFloat(event.target.value));
        });

        // อัปเดตค่า Pitch ครั้งแรกเมื่อโหลดหน้าเว็บ เพื่อให้ตรงกับค่าเริ่มต้นของแถบเลื่อน
        updatePitch(parseFloat(whammyRange.value));

        // จัดการนโยบายการเล่นเสียงอัตโนมัติของเบราว์เซอร์
        // หาก AudioContext ถูกระงับ (suspended) (เช่น ก่อนที่ผู้ใช้จะมีการโต้ตอบ)
        // ให้กลับมาทำงานต่อเมื่อมีการโต้ตอบครั้งแรก
        document.addEventListener('DOMContentLoaded', () => {
            if (audioContext && audioContext.state === 'suspended') {
                audioContext.resume();
            }
        });
    </script>
</body>
</html>

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: