<!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>
To embed this project on your website, copy the following code and paste it into your website's HTML: