Tai Phan Mem Pitch Shifter - Html5 [best] Jun 2026
: A WebAssembly build of the world-class Rubber Band library, known for high-quality time-stretching and pitch-shifting with minimal artifacts. Pitchshift.js
<script> (function(){ // --- DOM elements --- const pitchSlider = document.getElementById('pitchSlider'); const pitchDisplay = document.getElementById('pitchDisplay'); const pitchFactorSpan = document.getElementById('pitchFactorSpan'); const playBtn = document.getElementById('playBtn'); const pauseStopBtn = document.getElementById('pauseStopBtn'); const audioUpload = document.getElementById('audioUpload'); const statusTextSpan = document.getElementById('statusText'); const fileInfoSpan = document.getElementById('fileInfo');
function pauseAudio() { if (!isPlaying || !sourceNode || !audioContext) return; // Capture current playback position: audioContext.currentTime gives the time line, but source started at startTime. // we need to compute offset based on elapsed time of current source considering playbackRate. // Since we need precise offset for resume, we track using audioContext's currentTime and source start metadata. // Simpler approach: get current time from context and compute elapsed from buffer start (startTime) if (sourceNode && audioContext) { // The source started at startTime (which we store when starting). But we didn't store startTime in createAndStartSource. Let's refactor. // better: store sourceStartTime globally. if (window._sourceStartTime !== undefined && audioContext) const now = audioContext.currentTime; const elapsed = (now - window._sourceStartTime) * sourceNode.playbackRate.value; let newOffset = pauseOffset + elapsed; if (newOffset >= audioBuffer.duration) newOffset = audioBuffer.duration; pauseOffset = newOffset; else // fallback: if no start time stored, just keep offset console.warn("fallback pause offset");
</body> </html>
input[type="range"]:focus outline: none;
const newSource = audioContext.createBufferSource(); newSource.buffer = audioBuffer; const rate = semitonesToRate(currentPitchSemitones); newSource.playbackRate.value = rate; newSource.connect(audioContext.destination); newSource.start(0, offsetSec); sourceNode = newSource; isPlaying = true; // when buffer ends naturally, reset play state newSource.onended = () => if (sourceNode === newSource) isPlaying = false; pauseOffset = 0; sourceNode = null; updatePlayButtonsState(); statusTextSpan.innerText = "Finished"; setTimeout(() => if (audioBuffer && !isPlaying) statusTextSpan.innerText = "Stopped"; , 1200);
h1 font-size: 1.9rem; font-weight: 700; margin: 0 0 0.2rem 0; background: linear-gradient(135deg, #E0F2FE, #7AA9FF); -webkit-background-clip: text; background-clip: text; color: transparent; letter-spacing: -0.3px; display: flex; align-items: center; gap: 10px; tai phan mem pitch shifter - html5
if (sourceNode) { try sourceNode.stop(); catch(e) {} sourceNode.disconnect(); } const newSource = audioContext.createBufferSource(); newSource.buffer = audioBuffer; const rate = semitonesToRate(currentPitchSemitones); newSource.playbackRate.value = rate; newSource.connect(audioContext.destination); const startTime = audioContext.currentTime; newSource.start(startTime, offsetSec); sourceNode = newSource; window._sourceStartTime = startTime; isPlaying = true; newSource.onended = () => if (sourceNode === newSource) isPlaying = false; // if ended naturally, reset pauseOffset pauseOffset = 0; sourceNode = null; window._sourceStartTime = null; updatePlayButtonsState(); statusTextSpan.innerText = "Stopped";
Đây là tiện ích phổ biến nhất trên Chrome Web Store. Nó cho phép bạn thay đổi cao độ (pitch) của bất kỳ video HTML5 nào mà không làm thay đổi tốc độ phát (playback rate).
// Event binding pitchSlider.addEventListener('input', (e) => { const val = parseFloat(e.target.value); updatePitchUI(val); // If currently playing, dynamically update the playback rate on the fly if (sourceNode && isPlaying && audioContext && audioContext.state === 'running') { try sourceNode.playbackRate.value = semitonesToRate(currentPitchSemitones); catch(err) {} } }); : A WebAssembly build of the world-class Rubber
function initAudioContext()
// Create a new source from current audioBuffer, applying current pitch rate, and start at 'when' (relative to ctx currentTime) // offsetSec: where to start in buffer (seconds) function createAndStartSource(offsetSec) { if (!audioContext || !audioBuffer) return null; // ensure context is running (resume if suspended) if (audioContext.state === 'suspended') audioContext.resume().then(() => createAndStartSource(offsetSec); ).catch(e => console.warn("AudioContext resume failed", e)); return null;